mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-4168 Root Admin should be able to create 'ExplicitDedication' affinity group at domain level and make it available for all accounts in the domain
Changes: - 'ExcplicitDedication' type of group can be created/deleted by Root admin only - Users can no longer create this type of affinity group - RootAdmin can create this type of affinitygroup at domain level. Such a domain level group is available for all accounts in that domain for listing and for use during deployVM. - The domain level affinitygroup should be visible to the users in that domain, domain admins and Root admin. Conflicts: server/src/com/cloud/api/query/QueryManagerImpl.java server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java
This commit is contained in:
parent
495259132c
commit
a06bd9fa2b
@ -28,4 +28,6 @@ public interface AffinityGroup extends ControlledEntity, InternalIdentity, Ident
|
||||
|
||||
String getType();
|
||||
|
||||
ACLType getAclType();
|
||||
|
||||
}
|
||||
|
||||
@ -58,4 +58,23 @@ public interface AffinityGroupProcessor extends Adapter {
|
||||
*/
|
||||
boolean check(VirtualMachineProfile vm, DeployDestination plannedDestination)
|
||||
throws AffinityConflictException;
|
||||
|
||||
/**
|
||||
* isAdminControlledGroup() should return true if the affinity/anti-affinity
|
||||
* group can only be operated on[create/delete/modify] by the Admin
|
||||
*
|
||||
* @return boolean true/false
|
||||
*/
|
||||
boolean isAdminControlledGroup();
|
||||
|
||||
|
||||
/**
|
||||
* canBeSharedDomainWide() should return true if the affinity/anti-affinity
|
||||
* group can be created for a domain and shared by all accounts under the
|
||||
* domain.
|
||||
*
|
||||
* @return boolean true/false
|
||||
*/
|
||||
boolean canBeSharedDomainWide();
|
||||
|
||||
}
|
||||
@ -75,4 +75,8 @@ public interface AffinityGroupService {
|
||||
|
||||
boolean isAffinityGroupProcessorAvailable(String affinityGroupType);
|
||||
|
||||
boolean isAdminControlledGroup(AffinityGroup group);
|
||||
|
||||
boolean isAffinityGroupAvailableInDomain(long affinityGroupId, long domainId);
|
||||
|
||||
}
|
||||
|
||||
@ -47,4 +47,14 @@ public class AffinityProcessorBase extends AdapterBase implements AffinityGroupP
|
||||
throws AffinityConflictException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdminControlledGroup() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeSharedDomainWide() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,6 +377,7 @@
|
||||
<bean id="StaticRoleBasedAPIAccessChecker" class="org.apache.cloudstack.acl.StaticRoleBasedAPIAccessChecker"/>
|
||||
<bean id="databaseIntegrityChecker" class="com.cloud.upgrade.DatabaseIntegrityChecker" />
|
||||
<bean id="domainChecker" class="com.cloud.acl.DomainChecker" />
|
||||
<bean id="affinityGroupAccessChecker" class="com.cloud.acl.AffinityGroupAccessChecker" />
|
||||
|
||||
<!--
|
||||
Authenticators
|
||||
@ -929,6 +930,8 @@
|
||||
</bean>
|
||||
<bean id="AffinityGroupVMMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDaoImpl">
|
||||
</bean>
|
||||
<bean id="AffinityGroupDomainMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDaoImpl">
|
||||
</bean>
|
||||
|
||||
<bean id="PlannerHostReservationDaoImpl" class="com.cloud.deploy.dao.PlannerHostReservationDaoImpl">
|
||||
</bean>
|
||||
|
||||
@ -146,6 +146,7 @@
|
||||
<bean id="securityCheckers" class="com.cloud.utils.component.AdapterList">
|
||||
<property name="Adapters">
|
||||
<list>
|
||||
<ref bean="affinityGroupAccessChecker"/>
|
||||
<ref bean="domainChecker"/>
|
||||
</list>
|
||||
</property>
|
||||
|
||||
@ -65,7 +65,7 @@ public class AccountVO implements Account {
|
||||
|
||||
@Column(name="default_zone_id")
|
||||
private Long defaultZoneId = null;
|
||||
|
||||
|
||||
@Column(name = "default")
|
||||
boolean isDefault;
|
||||
|
||||
@ -77,7 +77,7 @@ public class AccountVO implements Account {
|
||||
this.id = id;
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
|
||||
public AccountVO(String accountName, long domainId, String networkDomain, short type, String uuid) {
|
||||
this.accountName = accountName;
|
||||
this.domainId = domainId;
|
||||
@ -161,7 +161,7 @@ public class AccountVO implements Account {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("Acct[").append(id).append("-").append(accountName).append("]").toString();
|
||||
return new StringBuilder("Acct[").append(uuid).append("-").append(accountName).append("]").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
// 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 javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.cloud.domain.PartOf;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
@Entity
|
||||
@Table(name = "affinity_group_domain_map")
|
||||
public class AffinityGroupDomainMapVO implements PartOf, InternalIdentity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
long id;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
long domainId;
|
||||
|
||||
@Column(name = "affinity_group_id")
|
||||
private long affinityGroupId;
|
||||
|
||||
@Column(name = "subdomain_access")
|
||||
public Boolean subdomainAccess;
|
||||
|
||||
protected AffinityGroupDomainMapVO() {
|
||||
}
|
||||
|
||||
public AffinityGroupDomainMapVO(long affinityGroupId, long domainId, Boolean subdomainAccess) {
|
||||
this.affinityGroupId = affinityGroupId;
|
||||
this.domainId = domainId;
|
||||
this.subdomainAccess = subdomainAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public long getAffinityGroupId() {
|
||||
return affinityGroupId;
|
||||
}
|
||||
|
||||
public Boolean isSubdomainAccess() {
|
||||
return subdomainAccess;
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,11 +20,14 @@ import java.util.UUID;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
|
||||
@Entity
|
||||
@Table(name = ("affinity_group"))
|
||||
@ -52,17 +55,22 @@ public class AffinityGroupVO implements AffinityGroup {
|
||||
@Column(name = "uuid")
|
||||
private String uuid;
|
||||
|
||||
@Column(name = "acl_type")
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
ControlledEntity.ACLType aclType;
|
||||
|
||||
public AffinityGroupVO() {
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public AffinityGroupVO(String name, String type, String description, long domainId, long accountId) {
|
||||
public AffinityGroupVO(String name, String type, String description, long domainId, long accountId, ACLType aclType) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.domainId = domainId;
|
||||
this.accountId = accountId;
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
this.type = type;
|
||||
this.aclType = aclType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,6 +112,11 @@ public class AffinityGroupVO implements AffinityGroup {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControlledEntity.ACLType getAclType() {
|
||||
return aclType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder("AffinityGroup[");
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
// 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface AffinityGroupDomainMapDao extends GenericDao<AffinityGroupDomainMapVO, Long> {
|
||||
|
||||
AffinityGroupDomainMapVO findByAffinityGroup(long affinityGroupId);
|
||||
|
||||
List<AffinityGroupDomainMapVO> listByDomain(Object... domainId);
|
||||
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
// 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
|
||||
public class AffinityGroupDomainMapDaoImpl extends GenericDaoBase<AffinityGroupDomainMapVO, Long> implements
|
||||
AffinityGroupDomainMapDao {
|
||||
|
||||
private SearchBuilder<AffinityGroupDomainMapVO> ListByAffinityGroup;
|
||||
|
||||
private SearchBuilder<AffinityGroupDomainMapVO> DomainsSearch;
|
||||
|
||||
|
||||
public AffinityGroupDomainMapDaoImpl() {
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
ListByAffinityGroup = createSearchBuilder();
|
||||
ListByAffinityGroup.and("affinityGroupId", ListByAffinityGroup.entity().getAffinityGroupId(),
|
||||
SearchCriteria.Op.EQ);
|
||||
ListByAffinityGroup.done();
|
||||
|
||||
DomainsSearch = createSearchBuilder();
|
||||
DomainsSearch.and("domainId", DomainsSearch.entity().getDomainId(), Op.IN);
|
||||
DomainsSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffinityGroupDomainMapVO findByAffinityGroup(long affinityGroupId) {
|
||||
SearchCriteria<AffinityGroupDomainMapVO> sc = ListByAffinityGroup.create();
|
||||
sc.setParameters("affinityGroupId", affinityGroupId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AffinityGroupDomainMapVO> listByDomain(Object... domainId) {
|
||||
SearchCriteria<AffinityGroupDomainMapVO> sc = DomainsSearch.create();
|
||||
sc.setParameters("domainId", (Object[]) domainId);
|
||||
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
}
|
||||
@ -381,4 +381,13 @@ public class ExplicitDedicationProcessor extends AffinityProcessorBase implement
|
||||
return domainIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdminControlledGroup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeSharedDomainWide() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
80
server/src/com/cloud/acl/AffinityGroupAccessChecker.java
Normal file
80
server/src/com/cloud/acl/AffinityGroupAccessChecker.java
Normal file
@ -0,0 +1,80 @@
|
||||
// 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 com.cloud.acl;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
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.exception.PermissionDeniedException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.DomainManager;
|
||||
|
||||
@Component
|
||||
@Local(value = SecurityChecker.class)
|
||||
public class AffinityGroupAccessChecker extends DomainChecker {
|
||||
|
||||
@Inject
|
||||
AffinityGroupService _affinityGroupService;
|
||||
@Inject
|
||||
AccountManager _accountMgr;
|
||||
@Inject
|
||||
AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
|
||||
|
||||
@Override
|
||||
public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType)
|
||||
throws PermissionDeniedException {
|
||||
if (entity instanceof AffinityGroup) {
|
||||
AffinityGroup group = (AffinityGroup) entity;
|
||||
|
||||
if (_affinityGroupService.isAdminControlledGroup(group)) {
|
||||
if (accessType != null && accessType == AccessType.ModifyEntry
|
||||
&& !_accountMgr.isRootAdmin(caller.getType())) {
|
||||
throw new PermissionDeniedException(caller + " does not have permission to operate with resource "
|
||||
+ entity);
|
||||
}
|
||||
}
|
||||
|
||||
if (group.getAclType() == ACLType.Domain) {
|
||||
if (!_affinityGroupService.isAffinityGroupAvailableInDomain(group.getId(), caller.getDomainId())) {
|
||||
throw new PermissionDeniedException("Affinity group is not available in domain id="
|
||||
+ caller.getDomainId());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
//acl_type account
|
||||
if (caller.getId() != group.getAccountId()) {
|
||||
throw new PermissionDeniedException(caller
|
||||
+ " does not have permission to operate with resource " + entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,7 @@ import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -121,6 +122,8 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
|
||||
return true;
|
||||
} else if (entity instanceof Network && accessType != null && accessType == AccessType.UseNetwork) {
|
||||
_networkMgr.checkNetworkPermissions(caller, (Network) entity);
|
||||
} else if (entity instanceof AffinityGroup) {
|
||||
return false;
|
||||
} else {
|
||||
if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
|
||||
Account account = _accountDao.findById(entity.getAccountId());
|
||||
|
||||
@ -29,9 +29,11 @@ import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
|
||||
@ -137,6 +139,8 @@ import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.ha.HighAvailabilityManager;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.dao.NetworkDomainVO;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.security.SecurityGroupVMMapVO;
|
||||
import com.cloud.network.security.dao.SecurityGroupVMMapDao;
|
||||
import com.cloud.org.Grouping;
|
||||
@ -168,6 +172,8 @@ import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.DomainManager;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
@ -316,6 +322,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
||||
@Inject
|
||||
private DedicatedResourceDao _dedicatedDao;
|
||||
|
||||
@Inject
|
||||
DomainManager _domainMgr;
|
||||
|
||||
@Inject
|
||||
AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@ -3019,6 +3031,58 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
|
||||
|
||||
Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize);
|
||||
SearchCriteria<AffinityGroupJoinVO> sc = buildAffinityGroupSearchCriteria(domainId, isRecursive,
|
||||
permittedAccounts, listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType);
|
||||
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc,
|
||||
searchFilter);
|
||||
// search group details by ids
|
||||
List<AffinityGroupJoinVO> vrs = new ArrayList<AffinityGroupJoinVO>();
|
||||
Integer count = uniqueGroupsPair.second();
|
||||
if (count.intValue() != 0) {
|
||||
List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
|
||||
Long[] vrIds = new Long[uniqueGroups.size()];
|
||||
int i = 0;
|
||||
for (AffinityGroupJoinVO v : uniqueGroups) {
|
||||
vrIds[i++] = v.getId();
|
||||
}
|
||||
vrs = _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);
|
||||
vrs.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);
|
||||
|
||||
vrs.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);
|
||||
vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
|
||||
}
|
||||
|
||||
return new Pair<List<AffinityGroupJoinVO>, Integer>(vrs, vrs.size());
|
||||
|
||||
}
|
||||
|
||||
private SearchCriteria<AffinityGroupJoinVO> buildAffinityGroupSearchCriteria(Long domainId, boolean isRecursive,
|
||||
List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria,
|
||||
Long affinityGroupId, String affinityGroupName, String affinityGroupType) {
|
||||
|
||||
SearchBuilder<AffinityGroupJoinVO> groupSearch = _affinityGroupJoinDao.createSearchBuilder();
|
||||
_accountMgr.buildACLViewSearchBuilder(groupSearch, domainId, isRecursive, permittedAccounts,
|
||||
listProjectResourcesCriteria);
|
||||
@ -3042,22 +3106,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
||||
sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType);
|
||||
}
|
||||
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc,
|
||||
searchFilter);
|
||||
// search group details by ids
|
||||
Integer count = uniqueGroupsPair.second();
|
||||
if (count.intValue() == 0) {
|
||||
// empty result
|
||||
return uniqueGroupsPair;
|
||||
}
|
||||
List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
|
||||
Long[] vrIds = new Long[uniqueGroups.size()];
|
||||
int i = 0;
|
||||
for (AffinityGroupJoinVO v : uniqueGroups) {
|
||||
vrIds[i++] = v.getId();
|
||||
}
|
||||
List<AffinityGroupJoinVO> vrs = _affinityGroupJoinDao.searchByIds(vrIds);
|
||||
return new Pair<List<AffinityGroupJoinVO>, Integer>(vrs, count);
|
||||
return sc;
|
||||
|
||||
}
|
||||
|
||||
@ -3079,6 +3128,47 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
|
||||
return new Pair<List<AffinityGroupJoinVO>, Integer>(ags, count);
|
||||
}
|
||||
|
||||
private List<AffinityGroupJoinVO> listDomainLevelAffinityGroups(
|
||||
SearchCriteria<AffinityGroupJoinVO> sc, Filter searchFilter, long domainId) {
|
||||
List<Long> affinityGroupIds = new ArrayList<Long>();
|
||||
Set<Long> allowedDomains = _domainMgr.getDomainParentIds(domainId);
|
||||
List<AffinityGroupDomainMapVO> maps = _affinityGroupDomainMapDao.listByDomain(allowedDomains.toArray());
|
||||
|
||||
for (AffinityGroupDomainMapVO map : maps) {
|
||||
boolean subdomainAccess = map.isSubdomainAccess();
|
||||
if (map.getDomainId() == domainId || subdomainAccess) {
|
||||
affinityGroupIds.add(map.getAffinityGroupId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!affinityGroupIds.isEmpty()) {
|
||||
SearchCriteria<AffinityGroupJoinVO> domainSC = _affinityGroupJoinDao.createSearchCriteria();
|
||||
domainSC.addAnd("id", SearchCriteria.Op.IN, affinityGroupIds.toArray());
|
||||
domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString());
|
||||
|
||||
sc.addAnd("id", SearchCriteria.Op.SC, domainSC);
|
||||
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc,
|
||||
searchFilter);
|
||||
// search group by ids
|
||||
Integer count = uniqueGroupsPair.second();
|
||||
if (count.intValue() == 0) {
|
||||
// empty result
|
||||
return new ArrayList<AffinityGroupJoinVO>();
|
||||
}
|
||||
List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
|
||||
Long[] vrIds = new Long[uniqueGroups.size()];
|
||||
int i = 0;
|
||||
for (AffinityGroupJoinVO v : uniqueGroups) {
|
||||
vrIds[i++] = v.getId();
|
||||
}
|
||||
List<AffinityGroupJoinVO> vrs = _affinityGroupJoinDao.searchByIds(vrIds);
|
||||
return vrs;
|
||||
} else {
|
||||
return new ArrayList<AffinityGroupJoinVO>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResourceDetailResponse> listResource(ListResourceDetailsCmd cmd) {
|
||||
|
||||
|
||||
@ -23,6 +23,8 @@ import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
@Entity
|
||||
@ -85,6 +87,10 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
protected VirtualMachine.State vmState = null;
|
||||
|
||||
@Column(name = "acl_type")
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
ControlledEntity.ACLType aclType;
|
||||
|
||||
|
||||
public AffinityGroupJoinVO() {
|
||||
}
|
||||
@ -256,4 +262,14 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public ControlledEntity.ACLType getAclType() {
|
||||
return aclType;
|
||||
}
|
||||
|
||||
public void setAclType(ControlledEntity.ACLType aclType) {
|
||||
this.aclType = aclType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -44,6 +44,7 @@ import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
||||
import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
|
||||
import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
|
||||
@ -395,7 +396,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
Account account = ApiDBUtils.findAccountById(entity.getAccountId());
|
||||
domainId = account != null ? account.getDomainId() : -1;
|
||||
}
|
||||
if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate) && !(accessType != null && accessType == AccessType.UseNetwork)) {
|
||||
if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate)
|
||||
&& !(accessType != null && accessType == AccessType.UseNetwork)
|
||||
&& !(entity instanceof AffinityGroup)) {
|
||||
List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
|
||||
// for templates, we don't have to do cross domains check
|
||||
if (toBeChecked == null) {
|
||||
|
||||
@ -2572,13 +2572,27 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
+ " ,type: " + ag.getType() + " , Please try again after removing the affinity group");
|
||||
} else {
|
||||
// verify permissions
|
||||
_accountMgr.checkAccess(caller, null, true, owner, ag);
|
||||
// Root admin has access to both VM and AG by default, but
|
||||
// make sure the owner of these entities is same
|
||||
if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) {
|
||||
if (ag.getAccountId() != owner.getAccountId()) {
|
||||
throw new PermissionDeniedException("Affinity Group " + ag
|
||||
+ " does not belong to the VM's account");
|
||||
if (ag.getAclType() == ACLType.Domain) {
|
||||
_accountMgr.checkAccess(caller, null, false, owner, ag);
|
||||
// Root admin has access to both VM and AG by default,
|
||||
// but
|
||||
// make sure the owner of these entities is same
|
||||
if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) {
|
||||
if (!_affinityGroupService.isAffinityGroupAvailableInDomain(ag.getId(), owner.getDomainId())) {
|
||||
throw new PermissionDeniedException("Affinity Group " + ag
|
||||
+ " does not belong to the VM's domain");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_accountMgr.checkAccess(caller, null, true, owner, ag);
|
||||
// Root admin has access to both VM and AG by default,
|
||||
// but
|
||||
// make sure the owner of these entities is same
|
||||
if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getType())) {
|
||||
if (ag.getAccountId() != owner.getAccountId()) {
|
||||
throw new PermissionDeniedException("Affinity Group " + ag
|
||||
+ " does not belong to the VM's account");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,13 +20,18 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
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.context.CallContext;
|
||||
|
||||
@ -36,14 +41,20 @@ import org.springframework.context.annotation.Primary;
|
||||
|
||||
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.ActionEvent;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.exception.ResourceInUseException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.dao.NetworkDomainVO;
|
||||
import com.cloud.network.security.SecurityGroup;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.DomainManager;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
@ -79,9 +90,18 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
@Inject
|
||||
AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
|
||||
@Inject
|
||||
AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
|
||||
|
||||
@Inject
|
||||
private UserVmDao _userVmDao;
|
||||
|
||||
@Inject
|
||||
DomainDao _domainDao;
|
||||
|
||||
@Inject
|
||||
DomainManager _domainMgr;
|
||||
|
||||
protected List<AffinityGroupProcessor> _affinityProcessors;
|
||||
|
||||
public List<AffinityGroupProcessor> getAffinityGroupProcessors() {
|
||||
@ -92,20 +112,13 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
this._affinityProcessors = affinityProcessors;
|
||||
}
|
||||
|
||||
@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) {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
|
||||
|
||||
if (_affinityGroupDao.isNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName)) {
|
||||
throw new InvalidParameterValueException("Unable to create affinity group, a group with name "
|
||||
+ affinityGroupName
|
||||
+ " already exisits.");
|
||||
}
|
||||
|
||||
Account caller = UserContext.current().getCaller();
|
||||
|
||||
//validate the affinityGroupType
|
||||
Map<String, AffinityGroupProcessor> typeProcessorMap = getAffinityTypeToProcessorMap();
|
||||
@ -119,14 +132,65 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
"Unable to create affinity group, no Affinity Group Types configured");
|
||||
}
|
||||
|
||||
if (domainId == null) {
|
||||
domainId = owner.getDomainId();
|
||||
AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
|
||||
|
||||
if (processor.isAdminControlledGroup() && !_accountMgr.isRootAdmin(caller.getType())) {
|
||||
throw new PermissionDeniedException("Cannot create the affinity group");
|
||||
}
|
||||
|
||||
AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType, description, domainId,
|
||||
owner.getId());
|
||||
ControlledEntity.ACLType aclType = null;
|
||||
Account owner = null;
|
||||
|
||||
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.getType())) {
|
||||
// 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");
|
||||
}
|
||||
_accountMgr.checkAccess(caller, domain);
|
||||
|
||||
// domain level group, owner is SYSTEM.
|
||||
owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM);
|
||||
aclType = ControlledEntity.ACLType.Domain;
|
||||
|
||||
} else {
|
||||
owner = caller;
|
||||
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 exisits.");
|
||||
}
|
||||
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
|
||||
AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType, description, owner.getDomainId(),
|
||||
owner.getId(), aclType);
|
||||
_affinityGroupDao.persist(group);
|
||||
|
||||
if (domainId != null && aclType == ACLType.Domain) {
|
||||
AffinityGroupDomainMapVO domainMap = new AffinityGroupDomainMapVO(group.getId(), domainId, false);
|
||||
_affinityGroupDomainMapDao.persist(domainMap);
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Created affinity group =" + affinityGroupName);
|
||||
}
|
||||
@ -134,6 +198,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
@DB
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_DELETE, eventDescription = "Deleting affinity group")
|
||||
@ -163,7 +228,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
affinityGroupId = group.getId();
|
||||
}
|
||||
// check permissions
|
||||
_accountMgr.checkAccess(caller, null, true, group);
|
||||
_accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, group);
|
||||
|
||||
final Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
@ -251,12 +316,18 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
|
||||
@Override
|
||||
public List<String> listAffinityGroupTypes() {
|
||||
Account caller = UserContext.current().getCaller();
|
||||
|
||||
List<String> types = new ArrayList<String>();
|
||||
Map<String, AffinityGroupProcessor> componentMap = ComponentContext.getComponentsOfType(AffinityGroupProcessor.class);
|
||||
|
||||
if (componentMap.size() > 0) {
|
||||
for (Entry<String, AffinityGroupProcessor> entry : componentMap.entrySet()) {
|
||||
types.add(entry.getValue().getType());
|
||||
AffinityGroupProcessor processor = entry.getValue();
|
||||
if (processor.isAdminControlledGroup() && !_accountMgr.isRootAdmin(caller.getType())) {
|
||||
continue;
|
||||
}
|
||||
types.add(processor.getType());
|
||||
}
|
||||
|
||||
}
|
||||
@ -276,6 +347,23 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
return typeProcessorMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdminControlledGroup(AffinityGroup group) {
|
||||
|
||||
if (group != null) {
|
||||
String affinityGroupType = group.getType();
|
||||
Map<String, AffinityGroupProcessor> typeProcessorMap = getAffinityTypeToProcessorMap();
|
||||
if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) {
|
||||
AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
|
||||
if (processor != null) {
|
||||
return processor.isAdminControlledGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
|
||||
_name = name;
|
||||
@ -381,4 +469,29 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAffinityGroupAvailableInDomain(long affinityGroupId, long domainId) {
|
||||
Long groupDomainId = null;
|
||||
|
||||
AffinityGroupDomainMapVO domainMap = _affinityGroupDomainMapDao.findByAffinityGroup(affinityGroupId);
|
||||
if (domainMap == null) {
|
||||
return false;
|
||||
} else {
|
||||
groupDomainId = domainMap.getDomainId();
|
||||
}
|
||||
|
||||
if (domainId == groupDomainId.longValue()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (domainMap.subdomainAccess) {
|
||||
Set<Long> parentDomains = _domainMgr.getDomainParentIds(domainId);
|
||||
if (parentDomains.contains(groupDomainId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -33,6 +33,11 @@ import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.junit.After;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
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.test.utils.SpringUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
@ -57,6 +62,9 @@ import org.apache.cloudstack.test.utils.SpringUtils;
|
||||
|
||||
import com.cloud.dc.dao.DedicatedResourceDao;
|
||||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.dc.dao.DedicatedResourceDao;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.event.EventVO;
|
||||
import com.cloud.event.dao.EventDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
@ -67,6 +75,8 @@ import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.DomainManager;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
@ -135,7 +145,8 @@ public class AffinityApiUnitTest {
|
||||
when(_processor.getType()).thenReturn("mock");
|
||||
when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct);
|
||||
|
||||
AffinityGroupVO group = new AffinityGroupVO("group1", "mock", "mock group", domainId, 200L);
|
||||
AffinityGroupVO group = new AffinityGroupVO("group1", "mock", "mock group", domainId, 200L,
|
||||
ControlledEntity.ACLType.Account);
|
||||
Mockito.when(_affinityGroupDao.persist(Mockito.any(AffinityGroupVO.class))).thenReturn(group);
|
||||
Mockito.when(_affinityGroupDao.findById(Mockito.anyLong())).thenReturn(group);
|
||||
Mockito.when(_affinityGroupDao.findByAccountAndName(Mockito.anyLong(), Mockito.anyString())).thenReturn(group);
|
||||
@ -242,6 +253,11 @@ public class AffinityApiUnitTest {
|
||||
return Mockito.mock(AccountManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DomainManager domainManager() {
|
||||
return Mockito.mock(DomainManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EventDao eventDao() {
|
||||
return Mockito.mock(EventDao.class);
|
||||
@ -255,6 +271,16 @@ public class AffinityApiUnitTest {
|
||||
@Bean
|
||||
public UserDao userDao() {
|
||||
return Mockito.mock(UserDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupDomainMapDao affinityGroupDomainMapDao() {
|
||||
return Mockito.mock(AffinityGroupDomainMapDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DomainDao domainDao() {
|
||||
return Mockito.mock(DomainDao.class);
|
||||
}
|
||||
|
||||
public static class Library implements TypeFilter {
|
||||
|
||||
@ -410,6 +410,7 @@ CREATE TABLE `cloud`.`affinity_group` (
|
||||
`description` varchar(4096) NULL,
|
||||
`domain_id` bigint unsigned NOT NULL,
|
||||
`account_id` bigint unsigned NOT NULL,
|
||||
`acl_type` varchar(15) NOT NULL COMMENT 'ACL access type. can be Account/Domain',
|
||||
UNIQUE (`name`, `account_id`),
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_affinity_group__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`),
|
||||
@ -417,6 +418,7 @@ CREATE TABLE `cloud`.`affinity_group` (
|
||||
CONSTRAINT `uc_affinity_group__uuid` UNIQUE (`uuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
CREATE TABLE `cloud`.`affinity_group_vm_map` (
|
||||
`id` bigint unsigned NOT NULL auto_increment,
|
||||
`affinity_group_id` bigint unsigned NOT NULL,
|
||||
@ -426,7 +428,15 @@ CREATE TABLE `cloud`.`affinity_group_vm_map` (
|
||||
CONSTRAINT `fk_affinity_group_vm_map___instance_id` FOREIGN KEY(`instance_id`) REFERENCES `user_vm` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
CREATE TABLE `cloud`.`affinity_group_domain_map` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`domain_id` bigint unsigned NOT NULL COMMENT 'domain id',
|
||||
`affinity_group_id` bigint unsigned NOT NULL COMMENT 'affinity group id',
|
||||
`subdomain_access` int(1) unsigned COMMENT '1 if affinity group can be accessible from the subdomain',
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_affinity_group_domain_map__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_affinity_group_domain_map__affinity_group_id` FOREIGN KEY (`affinity_group_id`) REFERENCES `affinity_group`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `cloud`.`dedicated_resources` (
|
||||
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id',
|
||||
@ -898,6 +908,7 @@ CREATE VIEW `cloud`.`affinity_group_view` AS
|
||||
affinity_group.type type,
|
||||
affinity_group.description description,
|
||||
affinity_group.uuid uuid,
|
||||
affinity_group.acl_type acl_type,
|
||||
account.id account_id,
|
||||
account.uuid account_uuid,
|
||||
account.account_name account_name,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user