mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-6276 Fixing affinity groups for projects
This commit is contained in:
parent
92913a154c
commit
c76d317150
@ -56,12 +56,20 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie
|
||||
@Param(description = "the domain name of the affinity group")
|
||||
private String domainName;
|
||||
|
||||
@SerializedName(ApiConstants.PROJECT_ID)
|
||||
@Param(description = "the project ID of the affinity group")
|
||||
private String projectId;
|
||||
|
||||
@SerializedName(ApiConstants.PROJECT)
|
||||
@Param(description = "the project name of the affinity group")
|
||||
private String projectName;
|
||||
|
||||
@SerializedName(ApiConstants.TYPE)
|
||||
@Param(description = "the type of the affinity group")
|
||||
private String type;
|
||||
|
||||
@SerializedName("virtualmachineIds")
|
||||
@Param(description = "virtual machine Ids associated with this affinity group ")
|
||||
@Param(description = "virtual machine IDs associated with this affinity group")
|
||||
private List<String> vmIdList;
|
||||
|
||||
public AffinityGroupResponse() {
|
||||
@ -134,14 +142,12 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie
|
||||
|
||||
@Override
|
||||
public void setProjectId(String projectId) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProjectName(String projectName) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
public void setVMIdList(List<String> vmIdList) {
|
||||
|
||||
@ -18,47 +18,36 @@ package org.apache.cloudstack.affinity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd;
|
||||
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
public interface AffinityGroupService {
|
||||
|
||||
/**
|
||||
* Creates an affinity/anti-affinity group for the given account/domain.
|
||||
*
|
||||
* @param account
|
||||
* @param accountName
|
||||
* @param projectId
|
||||
* @param domainId
|
||||
* @param name
|
||||
* @param type
|
||||
* @param affinityGroupName
|
||||
* @param affinityGroupType
|
||||
* @param description
|
||||
* @return AffinityGroup
|
||||
*/
|
||||
AffinityGroup createAffinityGroup(String accountName, Long projectId, Long domainId, String affinityGroupName, String affinityGroupType, String description);
|
||||
|
||||
AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName, String affinityGroupType, String description);
|
||||
AffinityGroup createAffinityGroup(CreateAffinityGroupCmd createAffinityGroupCmd);
|
||||
|
||||
/**
|
||||
* Creates an affinity/anti-affinity group.
|
||||
*
|
||||
* @param affinityGroupId
|
||||
* @param account
|
||||
* @param accountName
|
||||
* @param domainId
|
||||
* @param affinityGroupName
|
||||
*/
|
||||
boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName);
|
||||
|
||||
/** Lists Affinity Groups in your account
|
||||
* @param account
|
||||
* @param domainId
|
||||
* @param affinityGroupId
|
||||
* @param affinityGroupName
|
||||
* @param affinityGroupType
|
||||
* @param vmId
|
||||
* @param startIndex
|
||||
* @param pageSize
|
||||
* @return
|
||||
*/
|
||||
Pair<List<? extends AffinityGroup>, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId, Long startIndex,
|
||||
Long pageSize);
|
||||
boolean deleteAffinityGroup(Long affinityGroupId, String accountName, Long projectId, Long domainId, String affinityGroupName);
|
||||
|
||||
/**
|
||||
* List group types available in deployment
|
||||
@ -77,6 +66,5 @@ public interface AffinityGroupService {
|
||||
|
||||
boolean isAffinityGroupAvailableInDomain(long affinityGroupId, long domainId);
|
||||
|
||||
AffinityGroup createAffinityGroupInternal(String account, Long domainId, String affinityGroupName, String affinityGroupType, String description);
|
||||
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
package org.apache.cloudstack.api.command.user.affinitygroup;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
@ -28,6 +27,7 @@ import org.apache.cloudstack.api.BaseAsyncCreateCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.ProjectResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
@ -54,6 +54,12 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
|
||||
entityType = DomainResponse.class)
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.PROJECT_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = ProjectResponse.class,
|
||||
description = "create affinity group for project")
|
||||
private Long projectId;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the affinity group")
|
||||
private String description;
|
||||
|
||||
@ -90,6 +96,10 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
|
||||
return affinityGroupType;
|
||||
}
|
||||
|
||||
public Long getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////// API Implementation///////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
@ -101,23 +111,17 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Account account = CallContext.current().getCallingAccount();
|
||||
if ((account == null) || _accountService.isAdmin(account.getId())) {
|
||||
if ((domainId != null) && (accountName != null)) {
|
||||
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
|
||||
if (userAccount != null) {
|
||||
return userAccount.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
if (account != null) {
|
||||
return account.getId();
|
||||
//For domain wide affinity groups (if the affinity group processor type allows it)
|
||||
if(projectId == null && domainId != null && accountName == null && _accountService.isRootAdmin(caller.getId())){
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
|
||||
// command to SYSTEM so ERROR events
|
||||
// are tracked
|
||||
Account owner = _accountService.finalizeOwner(caller, accountName, domainId, projectId);
|
||||
if(owner == null){
|
||||
return caller.getAccountId();
|
||||
}
|
||||
return owner.getAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,7 +138,7 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
|
||||
|
||||
@Override
|
||||
public void create() throws ResourceAllocationException {
|
||||
AffinityGroup result = _affinityGroupService.createAffinityGroup(accountName, domainId, affinityGroupName, affinityGroupType, description);
|
||||
AffinityGroup result = _affinityGroupService.createAffinityGroup(this);
|
||||
if (result != null) {
|
||||
setEntityId(result.getId());
|
||||
setEntityUuid(result.getUuid());
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
package org.apache.cloudstack.api.command.user.affinitygroup;
|
||||
|
||||
|
||||
import org.apache.cloudstack.api.response.ProjectResponse;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
@ -35,7 +35,6 @@ import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class, entityType = {AffinityGroup.class},
|
||||
@ -67,6 +66,9 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "The name of the affinity group. Mutually exclusive with ID parameter")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, description = "the project of the affinity group", entityType = ProjectResponse.class)
|
||||
private Long projectId;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@ -79,22 +81,11 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public Long getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
if (id != null && name != null) {
|
||||
throw new InvalidParameterValueException("name and id parameters are mutually exclusive");
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
id = _responseGenerator.getAffinityGroupId(name, getEntityOwnerId());
|
||||
if (id == null) {
|
||||
throw new InvalidParameterValueException("Unable to find affinity group by name " + name + " for the account ID=" + getEntityOwnerId());
|
||||
}
|
||||
}
|
||||
|
||||
if (id == null) {
|
||||
throw new InvalidParameterValueException("Either ID or name parameter is required by deleteAffinityGroup command");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -109,29 +100,22 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Account account = CallContext.current().getCallingAccount();
|
||||
if ((account == null) || _accountService.isAdmin(account.getId())) {
|
||||
if ((domainId != null) && (accountName != null)) {
|
||||
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
|
||||
if (userAccount != null) {
|
||||
return userAccount.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
if (account != null) {
|
||||
return account.getId();
|
||||
//For domain wide affinity groups (if the affinity group processor type allows it)
|
||||
if(projectId == null && domainId != null && accountName == null && _accountService.isRootAdmin(caller.getId())){
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
|
||||
// command to SYSTEM so ERROR events
|
||||
// are tracked
|
||||
|
||||
Account owner = _accountService.finalizeOwner(caller, accountName, domainId, projectId);
|
||||
if(owner == null){
|
||||
return caller.getAccountId();
|
||||
}
|
||||
return owner.getAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, domainId, name);
|
||||
boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, projectId, domainId, name);
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
setResponseObject(response);
|
||||
|
||||
@ -23,14 +23,14 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandJobType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
|
||||
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
|
||||
@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class, entityType = {AffinityGroup.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd {
|
||||
public class ListAffinityGroupsCmd extends BaseListProjectAndAccountResourcesCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName());
|
||||
|
||||
private static final String s_name = "listaffinitygroupsresponse";
|
||||
@ -69,6 +69,10 @@ public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getAffinityGroupType() {
|
||||
return affinityGroupType;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@ -80,13 +84,9 @@ public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
|
||||
ListResponse<AffinityGroupResponse> response = _queryService.listAffinityGroups(id, affinityGroupName,
|
||||
affinityGroupType, virtualMachineId, getAccountName(), getDomainId(), isRecursive(),
|
||||
listAll(), getStartIndex(), getPageSizeVal(), getKeyword());
|
||||
ListResponse<AffinityGroupResponse> response = _queryService.searchForAffinityGroups(this);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -31,6 +31,7 @@ import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
|
||||
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
|
||||
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
|
||||
import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd;
|
||||
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
|
||||
import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
|
||||
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
|
||||
@ -131,9 +132,7 @@ public interface QueryService {
|
||||
|
||||
ListResponse<TemplateResponse> listIsos(ListIsosCmd cmd);
|
||||
|
||||
ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
|
||||
String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive,
|
||||
boolean listAll, Long startIndex, Long pageSize, String keyword);
|
||||
ListResponse<AffinityGroupResponse> searchForAffinityGroups(ListAffinityGroupsCmd cmd);
|
||||
|
||||
List<ResourceDetailResponse> listResourceDetails(ListResourceDetailsCmd cmd);
|
||||
|
||||
@ -142,5 +141,4 @@ public interface QueryService {
|
||||
ListResponse<StorageTagResponse> searchForStorageTags(ListStorageTagsCmd cmd);
|
||||
|
||||
ListResponse<HostTagResponse> searchForHostTags(ListHostTagsCmd cmd);
|
||||
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ public class VMEntityManagerImpl implements VMEntityManager {
|
||||
try {
|
||||
dest = _dpMgr.planDeployment(vmProfile, plan, exclude, plannerToUse);
|
||||
} catch (AffinityConflictException e) {
|
||||
throw new CloudRuntimeException("Unable to create deployment, affinity rules associted to the VM conflict");
|
||||
throw new CloudRuntimeException("Unable to create deployment, affinity rules associated to the VM conflict");
|
||||
}
|
||||
|
||||
if (dest != null) {
|
||||
|
||||
@ -18,7 +18,6 @@ package org.apache.cloudstack.affinity.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
@ -34,9 +33,9 @@ public interface AffinityGroupDao extends GenericDao<AffinityGroupVO, Long> {
|
||||
|
||||
int removeByAccountId(long accountId);
|
||||
|
||||
AffinityGroup findDomainLevelGroupByName(Long domainId, String affinityGroupName);
|
||||
AffinityGroupVO findDomainLevelGroupByName(Long domainId, String affinityGroupName);
|
||||
|
||||
AffinityGroup findByAccountAndType(Long accountId, String string);
|
||||
AffinityGroupVO findByAccountAndType(Long accountId, String string);
|
||||
|
||||
AffinityGroup findDomainLevelGroupByType(Long domainId, String string);
|
||||
AffinityGroupVO findDomainLevelGroupByType(Long domainId, String string);
|
||||
}
|
||||
|
||||
@ -23,7 +23,6 @@ import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupVO;
|
||||
|
||||
@ -136,7 +135,7 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffinityGroup findDomainLevelGroupByName(Long domainId, String affinityGroupName) {
|
||||
public AffinityGroupVO findDomainLevelGroupByName(Long domainId, String affinityGroupName) {
|
||||
SearchCriteria<AffinityGroupVO> sc = DomainLevelNameSearch.create();
|
||||
sc.setParameters("aclType", ControlledEntity.ACLType.Domain);
|
||||
sc.setParameters("name", affinityGroupName);
|
||||
@ -145,7 +144,7 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffinityGroup findByAccountAndType(Long accountId, String type) {
|
||||
public AffinityGroupVO findByAccountAndType(Long accountId, String type) {
|
||||
SearchCriteria<AffinityGroupVO> sc = AccountIdTypeSearch.create();
|
||||
sc.setParameters("accountId", accountId);
|
||||
sc.setParameters("type", type);
|
||||
@ -154,7 +153,7 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffinityGroup findDomainLevelGroupByType(Long domainId, String type) {
|
||||
public AffinityGroupVO findDomainLevelGroupByType(Long domainId, String type) {
|
||||
SearchCriteria<AffinityGroupVO> sc = DomainLevelTypeSearch.create();
|
||||
sc.setParameters("aclType", ControlledEntity.ACLType.Domain);
|
||||
sc.setParameters("type", type);
|
||||
|
||||
@ -639,7 +639,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService {
|
||||
affinityGroupName = "DedicatedGrp-domain-" + domainName;
|
||||
}
|
||||
|
||||
group = _affinityGroupService.createAffinityGroupInternal(accountName, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
|
||||
group = _affinityGroupService.createAffinityGroup(accountName, null, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
|
||||
|
||||
return group;
|
||||
|
||||
@ -948,7 +948,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService {
|
||||
List<DedicatedResourceVO> resourcesInGroup = _dedicatedDao.listByAffinityGroupId(resource.getAffinityGroupId());
|
||||
if (resourcesInGroup.isEmpty()) {
|
||||
// delete the group
|
||||
_affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null);
|
||||
_affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -389,7 +389,7 @@ public class IntegrationTestConfiguration {
|
||||
}
|
||||
});
|
||||
Mockito.when(
|
||||
mock.createAffinityGroupInternal(Matchers.any(String.class), Matchers.any(Long.class), Matchers.any(String.class), Matchers.any(String.class),
|
||||
mock.createAffinityGroup(Matchers.any(String.class), Matchers.any(Long.class), Matchers.any(Long.class), Matchers.any(String.class), Matchers.any(String.class),
|
||||
Matchers.any(String.class))).thenReturn(gmock);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@ -19,17 +19,19 @@ package com.cloud.acl;
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupService;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.projects.ProjectVO;
|
||||
import com.cloud.projects.dao.ProjectAccountDao;
|
||||
import com.cloud.projects.dao.ProjectDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
@ -44,6 +46,10 @@ public class AffinityGroupAccessChecker extends DomainChecker {
|
||||
AccountManager _accountMgr;
|
||||
@Inject
|
||||
AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
|
||||
@Inject
|
||||
ProjectDao _projectDao;
|
||||
@Inject
|
||||
ProjectAccountDao _projectAccountDao;
|
||||
|
||||
@Override
|
||||
public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType) throws PermissionDeniedException {
|
||||
@ -51,8 +57,7 @@ public class AffinityGroupAccessChecker extends DomainChecker {
|
||||
AffinityGroup group = (AffinityGroup)entity;
|
||||
|
||||
if (_affinityGroupService.isAdminControlledGroup(group)) {
|
||||
if (accessType != null && accessType == AccessType.OperateEntry
|
||||
&& !_accountMgr.isRootAdmin(caller.getId())) {
|
||||
if (accessType == AccessType.OperateEntry && !_accountMgr.isRootAdmin(caller.getId())) {
|
||||
throw new PermissionDeniedException(caller + " does not have permission to operate with resource "
|
||||
+ entity);
|
||||
}
|
||||
@ -72,6 +77,15 @@ public class AffinityGroupAccessChecker extends DomainChecker {
|
||||
} else {
|
||||
//acl_type account
|
||||
if (caller.getId() != group.getAccountId()) {
|
||||
//check if the group belongs to a project
|
||||
ProjectVO project = _projectDao.findByProjectAccountId(group.getAccountId());
|
||||
if (project != null) {
|
||||
if (AccessType.ModifyProject.equals(accessType) && _projectAccountDao.canModifyProjectAccount(caller.getId(), group.getAccountId())) {
|
||||
return true;
|
||||
} else if (!AccessType.ModifyProject.equals(accessType) && _projectAccountDao.canAccessProjectAccount(caller.getId(), group.getAccountId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
throw new PermissionDeniedException(caller + " does not have permission to operate with resource " + entity);
|
||||
} else {
|
||||
return true;
|
||||
|
||||
@ -26,9 +26,6 @@ import java.util.Set;
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
@ -57,6 +54,7 @@ import org.apache.cloudstack.api.command.admin.volume.ListVolumesCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.admin.zone.ListZonesCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
|
||||
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
|
||||
import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd;
|
||||
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
|
||||
import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
|
||||
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
|
||||
@ -196,7 +194,6 @@ import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VolumeDetailsDao;
|
||||
import com.cloud.tags.ResourceTagVO;
|
||||
import com.cloud.tags.dao.ResourceTagDao;
|
||||
import com.cloud.template.VirtualMachineTemplate.State;
|
||||
@ -207,6 +204,7 @@ import com.cloud.user.DomainManager;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.db.Filter;
|
||||
@ -217,11 +215,12 @@ import com.cloud.utils.db.SearchCriteria.Func;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.NicDetailsDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
@Component
|
||||
@Local(value = {QueryService.class})
|
||||
@ -229,6 +228,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(QueryManagerImpl.class);
|
||||
|
||||
private static final String ID_FIELD = "id";
|
||||
|
||||
@Inject
|
||||
private AccountManager _accountMgr;
|
||||
|
||||
@ -331,12 +332,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
|
||||
@Inject
|
||||
private DomainRouterDao _routerDao;
|
||||
|
||||
@Inject
|
||||
private VolumeDetailsDao _volumeDetailDao;
|
||||
|
||||
@Inject
|
||||
private NicDetailsDao _nicDetailDao;
|
||||
|
||||
@Inject
|
||||
UserVmDetailsDao _userVmDetailDao;
|
||||
|
||||
@ -375,11 +370,11 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
|
||||
@Inject
|
||||
AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
|
||||
|
||||
|
||||
@Inject NetworkDetailsDao _networkDetailsDao;
|
||||
|
||||
@Inject
|
||||
ResourceTagDao _resourceTagDao;
|
||||
|
||||
@Inject
|
||||
DataStoreManager dataStoreManager;
|
||||
|
||||
@ -3395,55 +3390,60 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
|
||||
cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
|
||||
String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive,
|
||||
boolean listAll, Long startIndex, Long pageSize, String keyword) {
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> result = listAffinityGroupsInternal(affinityGroupId,
|
||||
affinityGroupName, affinityGroupType, vmId, accountName, domainId, isRecursive, listAll, startIndex,
|
||||
pageSize, keyword);
|
||||
public ListResponse<AffinityGroupResponse> searchForAffinityGroups(ListAffinityGroupsCmd cmd) {
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> result = searchForAffinityGroupsInternal(cmd);
|
||||
ListResponse<AffinityGroupResponse> response = new ListResponse<AffinityGroupResponse>();
|
||||
List<AffinityGroupResponse> agResponses = ViewResponseHelper.createAffinityGroupResponses(result.first());
|
||||
response.setResponses(agResponses, result.second());
|
||||
return response;
|
||||
}
|
||||
|
||||
public Pair<List<AffinityGroupJoinVO>, Integer> listAffinityGroupsInternal(Long affinityGroupId,
|
||||
String affinityGroupName, String affinityGroupType, Long vmId, String accountName, Long domainId,
|
||||
boolean isRecursive, boolean listAll, Long startIndex, Long pageSize, String keyword) {
|
||||
public Pair<List<AffinityGroupJoinVO>, Integer> searchForAffinityGroupsInternal(ListAffinityGroupsCmd cmd) {
|
||||
|
||||
final Long affinityGroupId = cmd.getId();
|
||||
final String affinityGroupName = cmd.getAffinityGroupName();
|
||||
final String affinityGroupType = cmd.getAffinityGroupType();
|
||||
final Long vmId = cmd.getVirtualMachineId();
|
||||
final String accountName = cmd.getAccountName();
|
||||
Long domainId = cmd.getDomainId();
|
||||
final Long projectId = cmd.getProjectId();
|
||||
Boolean isRecursive = cmd.isRecursive();
|
||||
final Boolean listAll = cmd.listAll();
|
||||
final Long startIndex = cmd.getStartIndex();
|
||||
final Long pageSize = cmd.getPageSizeVal();
|
||||
final String keyword = cmd.getKeyword();
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
caller.getAccountId();
|
||||
|
||||
if (vmId != null) {
|
||||
UserVmVO userVM = _userVmDao.findById(vmId);
|
||||
if (userVM == null) {
|
||||
throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance "
|
||||
+ vmId + "; instance not found.");
|
||||
throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found.");
|
||||
}
|
||||
_accountMgr.checkAccess(caller, null, true, userVM);
|
||||
return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize);
|
||||
}
|
||||
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
|
||||
domainId, isRecursive, null);
|
||||
_accountMgr.buildACLSearchParameters(caller, affinityGroupId, accountName, null, permittedAccounts,
|
||||
domainIdRecursiveListProject, listAll, true);
|
||||
domainId = domainIdRecursiveListProject.first();
|
||||
isRecursive = domainIdRecursiveListProject.second();
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
|
||||
Ternary<Long, Boolean, ListProjectResourcesCriteria> ternary = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, isRecursive, null);
|
||||
|
||||
Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize);
|
||||
SearchCriteria<AffinityGroupJoinVO> sc = buildAffinityGroupSearchCriteria(domainId, isRecursive,
|
||||
permittedAccounts, listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType, keyword);
|
||||
_accountMgr.buildACLSearchParameters(caller, affinityGroupId, accountName, projectId, permittedAccounts, ternary, listAll, false);
|
||||
|
||||
domainId = ternary.first();
|
||||
isRecursive = ternary.second();
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria = ternary.third();
|
||||
|
||||
Filter searchFilter = new Filter(AffinityGroupJoinVO.class, ID_FIELD, true, startIndex, pageSize);
|
||||
|
||||
SearchCriteria<AffinityGroupJoinVO> sc = buildAffinityGroupSearchCriteria(domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria, affinityGroupId,
|
||||
affinityGroupName, affinityGroupType, keyword);
|
||||
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, searchFilter);
|
||||
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc,
|
||||
searchFilter);
|
||||
// search group details by ids
|
||||
List<AffinityGroupJoinVO> vrs = new ArrayList<AffinityGroupJoinVO>();
|
||||
List<AffinityGroupJoinVO> affinityGroups = new ArrayList<AffinityGroupJoinVO>();
|
||||
|
||||
Integer count = uniqueGroupsPair.second();
|
||||
if (count.intValue() != 0) {
|
||||
List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
|
||||
@ -3452,36 +3452,33 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
|
||||
for (AffinityGroupJoinVO v : uniqueGroups) {
|
||||
vrIds[i++] = v.getId();
|
||||
}
|
||||
vrs = _affinityGroupJoinDao.searchByIds(vrIds);
|
||||
affinityGroups = _affinityGroupJoinDao.searchByIds(vrIds);
|
||||
}
|
||||
|
||||
if (!permittedAccounts.isEmpty()) {
|
||||
// add domain level affinity groups
|
||||
if (domainId != null) {
|
||||
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive,
|
||||
new ArrayList<Long>(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName,
|
||||
affinityGroupType, keyword);
|
||||
vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
|
||||
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria,
|
||||
affinityGroupId, affinityGroupName, affinityGroupType, keyword);
|
||||
affinityGroups.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
|
||||
} else {
|
||||
|
||||
for (Long permAcctId : permittedAccounts) {
|
||||
Account permittedAcct = _accountDao.findById(permAcctId);
|
||||
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(
|
||||
null, isRecursive, new ArrayList<Long>(),
|
||||
listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType, keyword);
|
||||
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria,
|
||||
affinityGroupId, affinityGroupName, affinityGroupType, keyword);
|
||||
|
||||
vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId()));
|
||||
affinityGroups.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId()));
|
||||
}
|
||||
}
|
||||
} else if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) {
|
||||
// list all domain level affinity groups for the domain admin case
|
||||
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive,
|
||||
new ArrayList<Long>(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName,
|
||||
affinityGroupType, keyword);
|
||||
vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
|
||||
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria,
|
||||
affinityGroupId, affinityGroupName, affinityGroupType, keyword);
|
||||
affinityGroups.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
|
||||
}
|
||||
|
||||
return new Pair<List<AffinityGroupJoinVO>, Integer>(vrs, vrs.size());
|
||||
return new Pair<List<AffinityGroupJoinVO>, Integer>(affinityGroups, affinityGroups.size());
|
||||
|
||||
}
|
||||
|
||||
@ -3526,9 +3523,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
|
||||
}
|
||||
}
|
||||
|
||||
private SearchCriteria<AffinityGroupJoinVO> buildAffinityGroupSearchCriteria(Long domainId, boolean isRecursive,
|
||||
List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria,
|
||||
Long affinityGroupId, String affinityGroupName, String affinityGroupType, String keyword) {
|
||||
private SearchCriteria<AffinityGroupJoinVO> buildAffinityGroupSearchCriteria(Long domainId, boolean isRecursive, List<Long> permittedAccounts,
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria, Long affinityGroupId, String affinityGroupName, String affinityGroupType, String keyword) {
|
||||
|
||||
SearchBuilder<AffinityGroupJoinVO> groupSearch = _affinityGroupJoinDao.createSearchBuilder();
|
||||
buildAffinityGroupViewSearchBuilder(groupSearch, domainId, isRecursive, permittedAccounts,
|
||||
@ -3538,8 +3534,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
|
||||
// distinct
|
||||
|
||||
SearchCriteria<AffinityGroupJoinVO> sc = groupSearch.create();
|
||||
buildAffinityGroupViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts,
|
||||
listProjectResourcesCriteria);
|
||||
buildAffinityGroupViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
|
||||
|
||||
if (affinityGroupId != null) {
|
||||
sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId);
|
||||
|
||||
@ -72,6 +72,15 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
|
||||
@Column(name = "domain_path")
|
||||
private String domainPath = null;
|
||||
|
||||
@Column(name = "project_id")
|
||||
private long projectId;
|
||||
|
||||
@Column(name = "project_uuid")
|
||||
private String projectUuid;
|
||||
|
||||
@Column(name = "project_name")
|
||||
private String projectName;
|
||||
|
||||
@Column(name = "vm_id")
|
||||
private long vmId;
|
||||
|
||||
@ -153,6 +162,20 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
|
||||
return domainPath;
|
||||
}
|
||||
|
||||
public long getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProjectUuid() {
|
||||
return projectUuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProjectName() {
|
||||
return projectName;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
@ -177,18 +200,6 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
|
||||
return vmState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProjectUuid() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProjectName() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public ControlledEntity.ACLType getAclType() {
|
||||
return aclType;
|
||||
}
|
||||
|
||||
@ -1484,7 +1484,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
final List<DedicatedResourceVO> resourcesInGroup = _dedicatedDao.listByAffinityGroupId(dr.getAffinityGroupId());
|
||||
if (resourcesInGroup.isEmpty()) {
|
||||
// delete the group
|
||||
_affinityGroupService.deleteAffinityGroup(dr.getAffinityGroupId(), null, null, null);
|
||||
_affinityGroupService.deleteAffinityGroup(dr.getAffinityGroupId(), null, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1702,7 +1702,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
final List<DedicatedResourceVO> resourcesInGroup = _dedicatedDao.listByAffinityGroupId(resource.getAffinityGroupId());
|
||||
if (resourcesInGroup.isEmpty()) {
|
||||
// delete the group
|
||||
_affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null);
|
||||
_affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1800,7 +1800,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
}
|
||||
|
||||
group = _affinityGroupService.createAffinityGroupInternal(accountName, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
|
||||
group = _affinityGroupService.createAffinityGroup(accountName, null, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
|
||||
|
||||
return group;
|
||||
|
||||
|
||||
@ -2406,98 +2406,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long>
|
||||
// permittedAccounts, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject,
|
||||
// boolean listAll, boolean forProjectInvitation) {
|
||||
// Long domainId = domainIdRecursiveListProject.first();
|
||||
// if (domainId != null) {
|
||||
// Domain domain = _domainDao.findById(domainId);
|
||||
// if (domain == null) {
|
||||
// throw new InvalidParameterValueException("Unable to find domain by id " + domainId);
|
||||
// }
|
||||
// // check permissions
|
||||
// checkAccess(caller, domain);
|
||||
// }
|
||||
//
|
||||
// if (accountName != null) {
|
||||
// if (projectId != null) {
|
||||
// throw new InvalidParameterValueException("Account and projectId can't be specified together");
|
||||
// }
|
||||
//
|
||||
// Account userAccount = null;
|
||||
// Domain domain = null;
|
||||
// if (domainId != null) {
|
||||
// userAccount = _accountDao.findActiveAccount(accountName, domainId);
|
||||
// domain = _domainDao.findById(domainId);
|
||||
// } else {
|
||||
// userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId());
|
||||
// domain = _domainDao.findById(caller.getDomainId());
|
||||
// }
|
||||
//
|
||||
// if (userAccount != null) {
|
||||
// checkAccess(caller, null, false, userAccount);
|
||||
// //check permissions
|
||||
// permittedAccounts.add(userAccount.getId());
|
||||
// } else {
|
||||
// throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // set project information
|
||||
// if (projectId != null) {
|
||||
// if (!forProjectInvitation) {
|
||||
// if (projectId.longValue() == -1) {
|
||||
// if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
|
||||
// permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId()));
|
||||
// } else {
|
||||
// domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.ListProjectResourcesOnly);
|
||||
// }
|
||||
// } else {
|
||||
// Project project = _projectMgr.getProject(projectId);
|
||||
// if (project == null) {
|
||||
// throw new InvalidParameterValueException("Unable to find project by id " + projectId);
|
||||
// }
|
||||
// if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
|
||||
// throw new PermissionDeniedException("Account " + caller + " can't access project id=" + projectId);
|
||||
// }
|
||||
// permittedAccounts.add(project.getProjectAccountId());
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if (id == null) {
|
||||
// domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources);
|
||||
// }
|
||||
// if (permittedAccounts.isEmpty() && domainId == null) {
|
||||
// if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
|
||||
// permittedAccounts.add(caller.getId());
|
||||
// } else if (!listAll) {
|
||||
// if (id == null) {
|
||||
// permittedAccounts.add(caller.getId());
|
||||
// } else if (!isRootAdmin(caller.getId())) {
|
||||
// domainIdRecursiveListProject.first(caller.getDomainId());
|
||||
// domainIdRecursiveListProject.second(true);
|
||||
// }
|
||||
// } else if (domainId == null) {
|
||||
// if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
|
||||
// domainIdRecursiveListProject.first(caller.getDomainId());
|
||||
// domainIdRecursiveListProject.second(true);
|
||||
// }
|
||||
// }
|
||||
// } else if (domainId != null) {
|
||||
// if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
|
||||
// permittedAccounts.add(caller.getId());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
//TODO: deprecate this to use the new buildACLSearchParameters with permittedDomains, permittedAccounts, and permittedResources as return
|
||||
@Override
|
||||
public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long>
|
||||
permittedAccounts, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject,
|
||||
boolean listAll, boolean forProjectInvitation) {
|
||||
public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedAccounts,
|
||||
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation) {
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
if (domainId != null) {
|
||||
Domain domain = _domainDao.findById(domainId);
|
||||
|
||||
@ -27,8 +27,8 @@ import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.utils.fsm.StateMachine2;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
@ -36,6 +36,7 @@ import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.framework.messagebus.PublishScope;
|
||||
@ -55,8 +56,6 @@ import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.JoinBuilder;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
@ -113,48 +112,29 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
@DB
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_CREATE, eventDescription = "Creating Affinity Group", create = true)
|
||||
public AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName, String affinityGroupType, String description) {
|
||||
public AffinityGroup createAffinityGroup(CreateAffinityGroupCmd createAffinityGroupCmd) {
|
||||
return createAffinityGroup(createAffinityGroupCmd.getAccountName(), createAffinityGroupCmd.getProjectId(), createAffinityGroupCmd.getDomainId(), createAffinityGroupCmd.getAffinityGroupName(), createAffinityGroupCmd.getAffinityGroupType(), createAffinityGroupCmd.getDescription());
|
||||
}
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
@DB
|
||||
@Override
|
||||
public AffinityGroup createAffinityGroup(final String accountName, final Long projectId, final Long domainId, final String affinityGroupName, final String affinityGroupType,
|
||||
final String description) {
|
||||
|
||||
// validate the affinityGroupType
|
||||
Map<String, AffinityGroupProcessor> typeProcessorMap = getAffinityTypeToProcessorMap();
|
||||
if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) {
|
||||
if (!typeProcessorMap.containsKey(affinityGroupType)) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type" + affinityGroupType);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (typeProcessorMap == null || typeProcessorMap.isEmpty()) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, no Affinity Group Types configured");
|
||||
}
|
||||
|
||||
AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
|
||||
|
||||
if (processor.isAdminControlledGroup()) {
|
||||
throw new PermissionDeniedException("Cannot create the affinity group");
|
||||
}
|
||||
|
||||
return createAffinityGroupInternal(account, domainId, affinityGroupName, affinityGroupType, description);
|
||||
}
|
||||
|
||||
@DB
|
||||
@Override
|
||||
public AffinityGroup createAffinityGroupInternal(String account, final Long domainId, final String affinityGroupName, final String affinityGroupType,
|
||||
final String description) {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
// validate the affinityGroupType
|
||||
Map<String, AffinityGroupProcessor> typeProcessorMap = getAffinityTypeToProcessorMap();
|
||||
if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) {
|
||||
if (!typeProcessorMap.containsKey(affinityGroupType)) {
|
||||
if(processor == null){
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type" + affinityGroupType);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, no Affinity Group Types configured");
|
||||
}
|
||||
|
||||
final AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
if (processor.isAdminControlledGroup() && !_accountMgr.isRootAdmin(caller.getId())) {
|
||||
throw new PermissionDeniedException("Cannot create the affinity group");
|
||||
}
|
||||
@ -163,72 +143,24 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
Account owner = null;
|
||||
boolean domainLevel = false;
|
||||
|
||||
if (account != null && domainId != null) {
|
||||
|
||||
owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
|
||||
aclType = ControlledEntity.ACLType.Account;
|
||||
|
||||
} else if (domainId != null && account == null) {
|
||||
|
||||
if (!_accountMgr.isRootAdmin(caller.getId())) {
|
||||
// non root admin need to pass both account and domain
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, account name must be passed with the domainId");
|
||||
} else if (!processor.canBeSharedDomainWide()) {
|
||||
// cannot be domain level
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, account name is needed");
|
||||
}
|
||||
|
||||
DomainVO domain = _domainDao.findById(domainId);
|
||||
if (domain == null) {
|
||||
throw new InvalidParameterValueException("Unable to find domain by specified id");
|
||||
}
|
||||
if (projectId == null && domainId != null && accountName == null) {
|
||||
verifyAccessToDomainWideProcessor(caller, processor);
|
||||
DomainVO domain = getDomain(domainId);
|
||||
_accountMgr.checkAccess(caller, domain);
|
||||
|
||||
// domain level group, owner is SYSTEM.
|
||||
owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM);
|
||||
aclType = ControlledEntity.ACLType.Domain;
|
||||
domainLevel = true;
|
||||
|
||||
} else {
|
||||
owner = caller;
|
||||
owner = _accountMgr.finalizeOwner(caller, accountName, domainId, projectId);
|
||||
aclType = ControlledEntity.ACLType.Account;
|
||||
}
|
||||
|
||||
if (_affinityGroupDao.isNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName)) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists.");
|
||||
}
|
||||
if (domainLevel && _affinityGroupDao.findDomainLevelGroupByName(domainId, affinityGroupName) != null) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists under the domain.");
|
||||
}
|
||||
verifyAffinityGroupNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName);
|
||||
verifyDomainLevelAffinityGroupName(domainLevel, owner.getDomainId(), affinityGroupName);
|
||||
|
||||
final Account ownerFinal = owner;
|
||||
final ControlledEntity.ACLType aclTypeFinal = aclType;
|
||||
AffinityGroupVO group = Transaction.execute(new TransactionCallback<AffinityGroupVO>() {
|
||||
@Override
|
||||
public AffinityGroupVO doInTransaction(TransactionStatus status) {
|
||||
AffinityGroupVO group =
|
||||
new AffinityGroupVO(affinityGroupName, affinityGroupType, description, ownerFinal.getDomainId(), ownerFinal.getId(), aclTypeFinal);
|
||||
_affinityGroupDao.persist(group);
|
||||
|
||||
if (domainId != null && aclTypeFinal == ACLType.Domain) {
|
||||
boolean subDomainAccess = false;
|
||||
subDomainAccess = processor.subDomainAccess();
|
||||
AffinityGroupDomainMapVO domainMap = new AffinityGroupDomainMapVO(group.getId(), domainId,
|
||||
subDomainAccess);
|
||||
_affinityGroupDomainMapDao.persist(domainMap);
|
||||
//send event for storing the domain wide resource access
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put(ApiConstants.ENTITY_TYPE, AffinityGroup.class);
|
||||
params.put(ApiConstants.ENTITY_ID, group.getId());
|
||||
params.put(ApiConstants.DOMAIN_ID, domainId);
|
||||
params.put(ApiConstants.SUBDOMAIN_ACCESS, subDomainAccess);
|
||||
_messageBus.publish(_name, EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, PublishScope.LOCAL,
|
||||
params);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
});
|
||||
AffinityGroupVO group = createAffinityGroup(processor, owner, aclType, affinityGroupName, affinityGroupType, description);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Created affinity group =" + affinityGroupName);
|
||||
@ -237,51 +169,135 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
return group;
|
||||
}
|
||||
|
||||
@DB
|
||||
private void verifyAccessToDomainWideProcessor(Account caller, AffinityGroupProcessor processor) {
|
||||
if (!_accountMgr.isRootAdmin(caller.getId())) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, account name must be passed with the domainId");
|
||||
}
|
||||
if (!processor.canBeSharedDomainWide()) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, account name is needed. Affinity group type "+ processor.getType() +" cannot be shared domain wide");
|
||||
}
|
||||
}
|
||||
|
||||
private AffinityGroupVO createAffinityGroup(final AffinityGroupProcessor processor, final Account owner, final ACLType aclType, final String affinityGroupName, final String affinityGroupType, final String description) {
|
||||
return Transaction.execute(new TransactionCallback<AffinityGroupVO>() {
|
||||
@Override
|
||||
public AffinityGroupVO doInTransaction(TransactionStatus status) {
|
||||
AffinityGroupVO group =
|
||||
new AffinityGroupVO(affinityGroupName, affinityGroupType, description, owner.getDomainId(), owner.getId(), aclType);
|
||||
_affinityGroupDao.persist(group);
|
||||
|
||||
if (aclType == ACLType.Domain) {
|
||||
boolean subDomainAccess = false;
|
||||
subDomainAccess = processor.subDomainAccess();
|
||||
AffinityGroupDomainMapVO domainMap = new AffinityGroupDomainMapVO(group.getId(), owner.getDomainId(),
|
||||
subDomainAccess);
|
||||
_affinityGroupDomainMapDao.persist(domainMap);
|
||||
//send event for storing the domain wide resource access
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put(ApiConstants.ENTITY_TYPE, AffinityGroup.class);
|
||||
params.put(ApiConstants.ENTITY_ID, group.getId());
|
||||
params.put(ApiConstants.DOMAIN_ID, owner.getDomainId());
|
||||
params.put(ApiConstants.SUBDOMAIN_ACCESS, subDomainAccess);
|
||||
_messageBus.publish(_name, EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, PublishScope.LOCAL,
|
||||
params);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private DomainVO getDomain(Long domainId) {
|
||||
DomainVO domain = _domainDao.findById(domainId);
|
||||
if (domain == null) {
|
||||
throw new InvalidParameterValueException("Unable to find domain by specified id");
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
|
||||
private void verifyAffinityGroupNameInUse(long accountId, long domainId, String affinityGroupName) {
|
||||
if (_affinityGroupDao.isNameInUse(accountId, domainId, affinityGroupName)) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyDomainLevelAffinityGroupName(boolean domainLevel, long domainId, String affinityGroupName) {
|
||||
if (domainLevel && _affinityGroupDao.findDomainLevelGroupByName(domainId, affinityGroupName) != null) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists under the domain.");
|
||||
}
|
||||
}
|
||||
|
||||
@DB
|
||||
@ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_DELETE, eventDescription = "Deleting affinity group")
|
||||
public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) {
|
||||
public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long projectId, Long domainId, String affinityGroupName) {
|
||||
|
||||
AffinityGroupVO group = getAffinityGroup(affinityGroupId, account, projectId, domainId, affinityGroupName);
|
||||
|
||||
// check permissions
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
|
||||
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, group);
|
||||
|
||||
final Long affinityGroupIdFinal = group.getId();
|
||||
deleteAffinityGroup(affinityGroupIdFinal);
|
||||
|
||||
// remove its related ACL permission
|
||||
Pair<Class<?>, Long> params = new Pair<Class<?>, Long>(AffinityGroup.class, affinityGroupIdFinal);
|
||||
_messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, params);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Deleted affinity group id=" + affinityGroupIdFinal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private AffinityGroupVO getAffinityGroup(Long affinityGroupId, String account, Long projectId, Long domainId, String affinityGroupName) {
|
||||
AffinityGroupVO group = null;
|
||||
if (affinityGroupId != null) {
|
||||
group = _affinityGroupDao.findById(affinityGroupId);
|
||||
if (group == null) {
|
||||
throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupId + "; failed to delete group.");
|
||||
}
|
||||
} else if (affinityGroupName != null) {
|
||||
group = _affinityGroupDao.findByAccountAndName(owner.getAccountId(), affinityGroupName);
|
||||
if (group == null) {
|
||||
throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupName + "; failed to delete group.");
|
||||
}
|
||||
group = getAffinityGroupByName(account, projectId, domainId, affinityGroupName);
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Either the affinity group Id or group name must be specified to delete the group");
|
||||
}
|
||||
if (affinityGroupId == null) {
|
||||
affinityGroupId = group.getId();
|
||||
if (group == null) {
|
||||
throw new InvalidParameterValueException("Unable to find affinity group " + (affinityGroupId == null ? affinityGroupName : affinityGroupId));
|
||||
}
|
||||
return group;
|
||||
}
|
||||
// check permissions
|
||||
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, group);
|
||||
|
||||
final Long affinityGroupIdFinal = affinityGroupId;
|
||||
private AffinityGroupVO getAffinityGroupByName(String account, Long projectId, Long domainId, String affinityGroupName) {
|
||||
AffinityGroupVO group = null;
|
||||
if(account == null && domainId != null){
|
||||
group = _affinityGroupDao.findDomainLevelGroupByName(domainId, affinityGroupName);
|
||||
}else{
|
||||
Long accountId = _accountMgr.finalyzeAccountId(account, domainId, projectId, true);
|
||||
if(accountId == null){
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
group = _affinityGroupDao.findByAccountAndName(caller.getAccountId(), affinityGroupName);
|
||||
}else{
|
||||
group = _affinityGroupDao.findByAccountAndName(accountId, affinityGroupName);
|
||||
}
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
private void deleteAffinityGroup(final Long affinityGroupId) {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
|
||||
AffinityGroupVO group = _affinityGroupDao.lockRow(affinityGroupIdFinal, true);
|
||||
AffinityGroupVO group = _affinityGroupDao.lockRow(affinityGroupId, true);
|
||||
if (group == null) {
|
||||
throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupIdFinal);
|
||||
throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId);
|
||||
}
|
||||
|
||||
List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupIdFinal);
|
||||
List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupId);
|
||||
if (!affinityGroupVmMap.isEmpty()) {
|
||||
SearchBuilder<AffinityGroupVMMapVO> listByAffinityGroup = _affinityGroupVMMapDao.createSearchBuilder();
|
||||
listByAffinityGroup.and("affinityGroupId", listByAffinityGroup.entity().getAffinityGroupId(), SearchCriteria.Op.EQ);
|
||||
listByAffinityGroup.done();
|
||||
SearchCriteria<AffinityGroupVMMapVO> sc = listByAffinityGroup.create();
|
||||
sc.setParameters("affinityGroupId", affinityGroupIdFinal);
|
||||
sc.setParameters("affinityGroupId", affinityGroupId);
|
||||
|
||||
_affinityGroupVMMapDao.lockRows(sc, null, true);
|
||||
_affinityGroupVMMapDao.remove(sc);
|
||||
@ -293,77 +309,15 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
processor.handleDeleteGroup(group);
|
||||
}
|
||||
|
||||
if(_affinityGroupDao.expunge(affinityGroupIdFinal)){
|
||||
if(_affinityGroupDao.expunge(affinityGroupId)){
|
||||
AffinityGroupDomainMapVO groupDomain = _affinityGroupDomainMapDao
|
||||
.findByAffinityGroup(affinityGroupIdFinal);
|
||||
.findByAffinityGroup(affinityGroupId);
|
||||
if (groupDomain != null) {
|
||||
_affinityGroupDomainMapDao.remove(groupDomain.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// remove its related ACL permission
|
||||
Pair<Class<?>, Long> params = new Pair<Class<?>, Long>(AffinityGroup.class, affinityGroupIdFinal);
|
||||
_messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, params);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Deleted affinity group id=" + affinityGroupId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<? extends AffinityGroup>, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId,
|
||||
Long startIndex, Long pageSize) {
|
||||
Filter searchFilter = new Filter(AffinityGroupVO.class, "id", Boolean.TRUE, startIndex, pageSize);
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
Long accountId = caller.getAccountId();
|
||||
Long domainId = caller.getDomainId();
|
||||
|
||||
SearchBuilder<AffinityGroupVMMapVO> vmInstanceSearch = _affinityGroupVMMapDao.createSearchBuilder();
|
||||
vmInstanceSearch.and("instanceId", vmInstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
|
||||
SearchBuilder<AffinityGroupVO> groupSearch = _affinityGroupDao.createSearchBuilder();
|
||||
|
||||
SearchCriteria<AffinityGroupVO> sc = groupSearch.create();
|
||||
|
||||
if (accountId != null) {
|
||||
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
|
||||
if (domainId != null) {
|
||||
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
|
||||
if (affinityGroupId != null) {
|
||||
sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId);
|
||||
}
|
||||
|
||||
if (affinityGroupName != null) {
|
||||
sc.addAnd("name", SearchCriteria.Op.EQ, affinityGroupName);
|
||||
}
|
||||
|
||||
if (affinityGroupType != null) {
|
||||
sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType);
|
||||
}
|
||||
|
||||
if (vmId != null) {
|
||||
UserVmVO userVM = _userVmDao.findById(vmId);
|
||||
if (userVM == null) {
|
||||
throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found.");
|
||||
}
|
||||
_accountMgr.checkAccess(caller, null, true, userVM);
|
||||
// add join to affinity_groups_vm_map
|
||||
groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch.entity().getAffinityGroupId(),
|
||||
JoinBuilder.JoinType.INNER);
|
||||
sc.setJoinParameters("vmInstanceSearch", "instanceId", vmId);
|
||||
}
|
||||
|
||||
Pair<List<AffinityGroupVO>, Integer> result = _affinityGroupDao.searchAndCount(sc, searchFilter);
|
||||
return new Pair<List<? extends AffinityGroup>, Integer>(result.first(), result.second());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -460,7 +414,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
// Verify input parameters
|
||||
UserVmVO vmInstance = _userVmDao.findById(vmId);
|
||||
if (vmInstance == null) {
|
||||
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
|
||||
throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId);
|
||||
}
|
||||
|
||||
// Check that the VM is stopped
|
||||
|
||||
@ -167,38 +167,39 @@ public class AffinityApiUnitTest {
|
||||
@Test
|
||||
public void createAffinityGroupTest() {
|
||||
when(_groupDao.isNameInUse(anyLong(), anyLong(), eq("group1"))).thenReturn(false);
|
||||
AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "mock", "affinity group one");
|
||||
AffinityGroup group = _affinityService.createAffinityGroup("user", null, domainId, "group1", "mock", "affinity group one");
|
||||
assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group);
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void invalidAffinityTypeTest() {
|
||||
AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "invalid", "affinity group one");
|
||||
AffinityGroup group = _affinityService.createAffinityGroup("user", null, domainId, "group1", "invalid", "affinity group one");
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void uniqueAffinityNameTest() {
|
||||
when(_groupDao.isNameInUse(anyLong(), anyLong(), eq("group1"))).thenReturn(true);
|
||||
AffinityGroup group2 = _affinityService.createAffinityGroup("user", domainId, "group1", "mock", "affinity group two");
|
||||
AffinityGroup group2 = _affinityService.createAffinityGroup("user", null, domainId, "group1", "mock", "affinity group two");
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void deleteAffinityGroupInvalidIdTest() throws ResourceInUseException {
|
||||
when(_groupDao.findById(20L)).thenReturn(null);
|
||||
_affinityService.deleteAffinityGroup(20L, "user", domainId, "group1");
|
||||
_affinityService.deleteAffinityGroup(20L, "user", null, domainId, "group1");
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void deleteAffinityGroupInvalidIdName() throws ResourceInUseException {
|
||||
when(_acctMgr.finalyzeAccountId("user", domainId, null, true)).thenReturn(200L);
|
||||
when(_groupDao.findByAccountAndName(200L, "group1")).thenReturn(null);
|
||||
_affinityService.deleteAffinityGroup(null, "user", domainId, "group1");
|
||||
_affinityService.deleteAffinityGroup(null, "user", null, domainId, "group1");
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void deleteAffinityGroupNullIdName() throws ResourceInUseException {
|
||||
_affinityService.deleteAffinityGroup(null, "user", domainId, null);
|
||||
_affinityService.deleteAffinityGroup(null, "user", null, domainId, null);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
|
||||
@ -0,0 +1,358 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.affinity;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.user.User;
|
||||
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
|
||||
import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
|
||||
import com.cloud.dc.dao.DedicatedResourceDao;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.EventVO;
|
||||
import com.cloud.event.dao.EventDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceInUseException;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.DomainManager;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.projects.dao.ProjectDao;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||
public class AffinityGroupServiceImplTest {
|
||||
|
||||
@Inject
|
||||
AffinityGroupServiceImpl _affinityService;
|
||||
|
||||
@Inject
|
||||
AccountManager _acctMgr;
|
||||
|
||||
@Inject
|
||||
AffinityGroupProcessor _processor;
|
||||
|
||||
@Inject
|
||||
AffinityGroupDao _groupDao;
|
||||
|
||||
@Inject
|
||||
UserVmDao _vmDao;
|
||||
|
||||
@Inject
|
||||
AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
|
||||
@Inject
|
||||
AffinityGroupDao _affinityGroupDao;
|
||||
|
||||
@Inject
|
||||
ActionEventUtils _eventUtils;
|
||||
|
||||
@Inject
|
||||
AccountDao _accountDao;
|
||||
|
||||
@Inject
|
||||
ProjectDao _projectDao;
|
||||
|
||||
@Inject
|
||||
EventDao _eventDao;
|
||||
|
||||
@Inject
|
||||
DedicatedResourceDao _dedicatedDao;
|
||||
|
||||
private static final long DOMAIN_ID = 5L;
|
||||
private static final long PROJECT_ID = 10L;
|
||||
private static final String ACCOUNT_NAME = "user";
|
||||
private static final String AFFINITY_GROUP_NAME = "group1";
|
||||
|
||||
private AccountVO acct;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws ConfigurationException {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ComponentContext.initComponentsLifeCycle();
|
||||
acct = new AccountVO(200L);
|
||||
acct.setType(Account.ACCOUNT_TYPE_NORMAL);
|
||||
acct.setAccountName(ACCOUNT_NAME);
|
||||
acct.setDomainId(DOMAIN_ID);
|
||||
|
||||
UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
|
||||
|
||||
CallContext.register(user, acct);
|
||||
|
||||
when(_processor.getType()).thenReturn("mock");
|
||||
when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct);
|
||||
|
||||
List<AffinityGroupProcessor> affinityProcessors = new ArrayList<AffinityGroupProcessor>();
|
||||
affinityProcessors.add(_processor);
|
||||
_affinityService.setAffinityGroupProcessors(affinityProcessors);
|
||||
|
||||
AffinityGroupVO group = new AffinityGroupVO(AFFINITY_GROUP_NAME, "mock", "mock group", DOMAIN_ID, 200L, ControlledEntity.ACLType.Account);
|
||||
Mockito.when(_affinityGroupDao.persist(Matchers.any(AffinityGroupVO.class))).thenReturn(group);
|
||||
Mockito.when(_affinityGroupDao.findById(Matchers.anyLong())).thenReturn(group);
|
||||
Mockito.when(_affinityGroupDao.findByAccountAndName(Matchers.anyLong(), Matchers.anyString())).thenReturn(group);
|
||||
Mockito.when(_affinityGroupDao.lockRow(Matchers.anyLong(), anyBoolean())).thenReturn(group);
|
||||
Mockito.when(_affinityGroupDao.expunge(Matchers.anyLong())).thenReturn(true);
|
||||
Mockito.when(_eventDao.persist(Matchers.any(EventVO.class))).thenReturn(new EventVO());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
CallContext.unregister();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAffinityGroupFromCmdTest() {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(false);
|
||||
CreateAffinityGroupCmd mockCreateAffinityGroupCmd = Mockito.mock(CreateAffinityGroupCmd.class);
|
||||
when(mockCreateAffinityGroupCmd.getProjectId()).thenReturn(PROJECT_ID);
|
||||
when(mockCreateAffinityGroupCmd.getAffinityGroupName()).thenReturn(AFFINITY_GROUP_NAME);
|
||||
when(mockCreateAffinityGroupCmd.getAffinityGroupType()).thenReturn("mock");
|
||||
when(mockCreateAffinityGroupCmd.getDescription()).thenReturn("affinity group one");
|
||||
AffinityGroup group = _affinityService.createAffinityGroup(mockCreateAffinityGroupCmd);
|
||||
assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAffinityGroupTest() {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(false);
|
||||
AffinityGroup group = _affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "mock", "affinity group one");
|
||||
assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDeleteDomainLevelAffinityGroup() {
|
||||
AffinityGroupVO mockGroup = Mockito.mock(AffinityGroupVO.class);
|
||||
when(mockGroup.getId()).thenReturn(2L);
|
||||
when(_affinityGroupDao.findById(Matchers.anyLong())).thenReturn(mockGroup);
|
||||
_affinityService.deleteAffinityGroup(2L, null, null, DOMAIN_ID, null);
|
||||
Mockito.verify(_affinityGroupDao).expunge(2L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDeleteAffintyGroupById() {
|
||||
AffinityGroupVO mockGroup = Mockito.mock(AffinityGroupVO.class);
|
||||
when(mockGroup.getId()).thenReturn(1L);
|
||||
when(_affinityGroupDao.findById(Matchers.anyLong())).thenReturn(mockGroup);
|
||||
_affinityService.deleteAffinityGroup(1L, ACCOUNT_NAME, null, DOMAIN_ID, null);
|
||||
Mockito.verify(_affinityGroupDao).expunge(1L);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void invalidAffinityTypeTest() {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
_affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "invalid", "affinity group one");
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void uniqueAffinityNameTest() {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(true);
|
||||
_affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "mock", "affinity group two");
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void deleteAffinityGroupInvalidIdTest() throws ResourceInUseException {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
when(_groupDao.findById(20L)).thenReturn(null);
|
||||
_affinityService.deleteAffinityGroup(20L, ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void deleteAffinityGroupInvalidIdName() throws ResourceInUseException {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
when(_acctMgr.finalyzeAccountId(ACCOUNT_NAME, DOMAIN_ID, null, true)).thenReturn(200L);
|
||||
when(_groupDao.findByAccountAndName(200L, AFFINITY_GROUP_NAME)).thenReturn(null);
|
||||
_affinityService.deleteAffinityGroup(null, ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void deleteAffinityGroupNullIdName() throws ResourceInUseException {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
_affinityService.deleteAffinityGroup(null, ACCOUNT_NAME, null, DOMAIN_ID, null);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void updateAffinityGroupVMRunning() throws ResourceInUseException {
|
||||
when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
|
||||
UserVmVO vm = new UserVmVO(10L, "test", "test", 101L, HypervisorType.Any, 21L, false, false, DOMAIN_ID, 200L, 1, 5L, "", "test", 1L);
|
||||
vm.setState(VirtualMachine.State.Running);
|
||||
when(_vmDao.findById(10L)).thenReturn(vm);
|
||||
|
||||
List<Long> affinityGroupIds = new ArrayList<Long>();
|
||||
affinityGroupIds.add(20L);
|
||||
|
||||
_affinityService.updateVMAffinityGroups(10L, affinityGroupIds);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = {AffinityGroupServiceImpl.class, ActionEventUtils.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false)
|
||||
public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public AccountDao accountDao() {
|
||||
return Mockito.mock(AccountDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProjectDao projectDao() {
|
||||
return Mockito.mock(ProjectDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AccountService accountService() {
|
||||
return Mockito.mock(AccountService.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupProcessor affinityGroupProcessor() {
|
||||
return Mockito.mock(AffinityGroupProcessor.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupDao affinityGroupDao() {
|
||||
return Mockito.mock(AffinityGroupDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupVMMapDao affinityGroupVMMapDao() {
|
||||
return Mockito.mock(AffinityGroupVMMapDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DedicatedResourceDao dedicatedResourceDao() {
|
||||
return Mockito.mock(DedicatedResourceDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AccountManager accountManager() {
|
||||
return Mockito.mock(AccountManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DomainManager domainManager() {
|
||||
return Mockito.mock(DomainManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EventDao eventDao() {
|
||||
return Mockito.mock(EventDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserVmDao userVMDao() {
|
||||
return Mockito.mock(UserVmDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserDao userDao() {
|
||||
return Mockito.mock(UserDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupDomainMapDao affinityGroupDomainMapDao() {
|
||||
return Mockito.mock(AffinityGroupDomainMapDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EntityManager entityManager() {
|
||||
return Mockito.mock(EntityManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DomainDao domainDao() {
|
||||
return Mockito.mock(DomainDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageBus messageBus() {
|
||||
return Mockito.mock(MessageBus.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationDao configDao() {
|
||||
return Mockito.mock(ConfigurationDao.class);
|
||||
}
|
||||
|
||||
public static class Library implements TypeFilter {
|
||||
|
||||
@Override
|
||||
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
|
||||
ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
|
||||
return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,3 +18,35 @@
|
||||
--;
|
||||
-- Schema upgrade from 4.6.0 to 4.6.1;
|
||||
--;
|
||||
DROP VIEW IF EXISTS `cloud`.`affinity_group_view`;
|
||||
CREATE VIEW `affinity_group_view`
|
||||
AS SELECT
|
||||
`affinity_group`.`id` AS `id`,
|
||||
`affinity_group`.`name` AS `name`,
|
||||
`affinity_group`.`type` AS `type`,
|
||||
`affinity_group`.`description` AS `description`,
|
||||
`affinity_group`.`uuid` AS `uuid`,
|
||||
`affinity_group`.`acl_type` AS `acl_type`,
|
||||
`account`.`id` AS `account_id`,
|
||||
`account`.`uuid` AS `account_uuid`,
|
||||
`account`.`account_name` AS `account_name`,
|
||||
`account`.`type` AS `account_type`,
|
||||
`domain`.`id` AS `domain_id`,
|
||||
`domain`.`uuid` AS `domain_uuid`,
|
||||
`domain`.`name` AS `domain_name`,
|
||||
`domain`.`path` AS `domain_path`,
|
||||
`projects`.`id` AS `project_id`,
|
||||
`projects`.`uuid` AS `project_uuid`,
|
||||
`projects`.`name` AS `project_name`,
|
||||
`vm_instance`.`id` AS `vm_id`,
|
||||
`vm_instance`.`uuid` AS `vm_uuid`,
|
||||
`vm_instance`.`name` AS `vm_name`,
|
||||
`vm_instance`.`state` AS `vm_state`,
|
||||
`user_vm`.`display_name` AS `vm_display_name`
|
||||
FROM `affinity_group`
|
||||
JOIN `account` ON`affinity_group`.`account_id` = `account`.`id`
|
||||
JOIN `domain` ON`affinity_group`.`domain_id` = `domain`.`id`
|
||||
LEFT JOIN `projects` ON`projects`.`project_account_id` = `account`.`id`
|
||||
LEFT JOIN `affinity_group_vm_map` ON`affinity_group`.`id` = `affinity_group_vm_map`.`affinity_group_id`
|
||||
LEFT JOIN `vm_instance` ON`vm_instance`.`id` = `affinity_group_vm_map`.`instance_id`
|
||||
LEFT JOIN `user_vm` ON`user_vm`.`id` = `vm_instance`.`id`;
|
||||
|
||||
1083
test/integration/component/test_affinity_groups_projects.py
Normal file
1083
test/integration/component/test_affinity_groups_projects.py
Normal file
File diff suppressed because it is too large
Load Diff
188
test/integration/smoke/test_affinity_groups_projects.py
Normal file
188
test/integration/smoke/test_affinity_groups_projects.py
Normal file
@ -0,0 +1,188 @@
|
||||
#!/usr/bin/env python
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from marvin.codes import FAILED
|
||||
from marvin.cloudstackTestCase import *
|
||||
from marvin.cloudstackAPI import *
|
||||
from marvin.lib.utils import *
|
||||
from marvin.lib.base import *
|
||||
from marvin.lib.common import *
|
||||
from marvin.sshClient import SshClient
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
class TestDeployVmWithAffinityGroup(cloudstackTestCase):
|
||||
"""
|
||||
This test deploys a virtual machine for a project
|
||||
using the small service offering and builtin template
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.testClient = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient()
|
||||
zone_name = cls.testClient.getZoneForTests()
|
||||
cls.apiclient = cls.testClient.getApiClient()
|
||||
cls.domain = get_domain(cls.apiclient)
|
||||
cls.services = cls.testClient.getParsedTestDataConfig()
|
||||
# Get Zone, Domain and templates
|
||||
cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
|
||||
|
||||
cls.template = get_template(
|
||||
cls.apiclient,
|
||||
cls.zone.id,
|
||||
cls.services["ostype"]
|
||||
)
|
||||
|
||||
if cls.template == FAILED:
|
||||
assert False, "get_template() failed to return template with description %s" % cls.services["ostype"]
|
||||
|
||||
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
||||
|
||||
cls.services["template"] = cls.template.id
|
||||
cls.services["zoneid"] = cls.zone.id
|
||||
|
||||
cls.account = Account.create(
|
||||
cls.apiclient,
|
||||
cls.services["account"],
|
||||
domainid=cls.domain.id
|
||||
)
|
||||
|
||||
projectData = {
|
||||
"name": "Project",
|
||||
"displaytext": "Test project",
|
||||
}
|
||||
|
||||
cls.project = Project.create(
|
||||
cls.apiclient,
|
||||
projectData,
|
||||
account=cls.account.name,
|
||||
domainid=cls.account.domainid
|
||||
)
|
||||
|
||||
# Add user to the project
|
||||
cls.project.addAccount(
|
||||
cls.apiclient,
|
||||
cls.account.name
|
||||
)
|
||||
|
||||
cls.service_offering = ServiceOffering.create(
|
||||
cls.apiclient,
|
||||
cls.services["service_offerings"]["tiny"]
|
||||
)
|
||||
|
||||
cls.ag = AffinityGroup.create(cls.apiclient, cls.services["virtual_machine"]["affinity"],projectid=cls.project.id)
|
||||
|
||||
cls._cleanup = [
|
||||
cls.service_offering,
|
||||
cls.ag,
|
||||
cls.project,
|
||||
cls.account,
|
||||
]
|
||||
return
|
||||
|
||||
@attr(tags=["basic", "advanced", "multihost"], required_hardware="false")
|
||||
def test_DeployVmAntiAffinityGroup_in_project(self):
|
||||
"""
|
||||
test DeployVM in anti-affinity groups for project
|
||||
|
||||
deploy VM1 and VM2 in the same host-anti-affinity groups
|
||||
Verify that the vms are deployed on separate hosts
|
||||
"""
|
||||
#deploy VM1 in affinity group created in setUp
|
||||
vm1 = VirtualMachine.create(
|
||||
self.apiclient,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
projectid=self.project.id,
|
||||
serviceofferingid=self.service_offering.id,
|
||||
affinitygroupnames=[self.ag.name]
|
||||
)
|
||||
|
||||
list_vm1 = list_virtual_machines(
|
||||
self.apiclient,
|
||||
id=vm1.id
|
||||
)
|
||||
self.assertEqual(
|
||||
isinstance(list_vm1, list),
|
||||
True,
|
||||
"Check list response returns a valid list"
|
||||
)
|
||||
self.assertNotEqual(
|
||||
len(list_vm1),
|
||||
0,
|
||||
"Check VM available in List Virtual Machines"
|
||||
)
|
||||
vm1_response = list_vm1[0]
|
||||
self.assertEqual(
|
||||
vm1_response.state,
|
||||
'Running',
|
||||
msg="VM is not in Running state"
|
||||
)
|
||||
self.assertEqual(
|
||||
vm1_response.projectid,
|
||||
self.project.id,
|
||||
msg="VM1 is not deployed in project"
|
||||
)
|
||||
host_of_vm1 = vm1_response.hostid
|
||||
|
||||
#deploy VM2 in affinity group created in setUp
|
||||
vm2 = VirtualMachine.create(
|
||||
self.apiclient,
|
||||
self.services["virtual_machine"],
|
||||
templateid=self.template.id,
|
||||
projectid=self.project.id,
|
||||
serviceofferingid=self.service_offering.id,
|
||||
affinitygroupnames=[self.ag.name]
|
||||
)
|
||||
list_vm2 = list_virtual_machines(
|
||||
self.apiclient,
|
||||
id=vm2.id
|
||||
)
|
||||
self.assertEqual(
|
||||
isinstance(list_vm2, list),
|
||||
True,
|
||||
"Check list response returns a valid list"
|
||||
)
|
||||
self.assertNotEqual(
|
||||
len(list_vm2),
|
||||
0,
|
||||
"Check VM available in List Virtual Machines"
|
||||
)
|
||||
vm2_response = list_vm2[0]
|
||||
self.assertEqual(
|
||||
vm2_response.state,
|
||||
'Running',
|
||||
msg="VM is not in Running state"
|
||||
)
|
||||
self.assertEqual(
|
||||
vm2_response.projectid,
|
||||
self.project.id,
|
||||
msg="VM2 is not deployed in project"
|
||||
)
|
||||
host_of_vm2 = vm2_response.hostid
|
||||
|
||||
self.assertNotEqual(host_of_vm1, host_of_vm2,
|
||||
msg="Both VMs of affinity group %s are on the same host" % self.ag.name)
|
||||
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
try:
|
||||
#Clean up, terminate the created templates
|
||||
cleanup_resources(cls.apiclient, cls._cleanup)
|
||||
except Exception as e:
|
||||
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||
@ -4220,7 +4220,7 @@ class AffinityGroup:
|
||||
self.__dict__.update(items)
|
||||
|
||||
@classmethod
|
||||
def create(cls, apiclient, aff_grp, account=None, domainid=None):
|
||||
def create(cls, apiclient, aff_grp, account=None, domainid=None, projectid=None):
|
||||
cmd = createAffinityGroup.createAffinityGroupCmd()
|
||||
cmd.name = aff_grp['name']
|
||||
cmd.displayText = aff_grp['name']
|
||||
@ -4229,6 +4229,8 @@ class AffinityGroup:
|
||||
cmd.account = account
|
||||
if domainid:
|
||||
cmd.domainid = domainid
|
||||
if projectid:
|
||||
cmd.projectid = projectid
|
||||
return AffinityGroup(apiclient.createAffinityGroup(cmd).__dict__)
|
||||
|
||||
def update(self, apiclient):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user