mirror of https://github.com/apache/cloudstack.git
Ensure affinity groups are honored when VMs are deployed in parallel (#9201)
This commit is contained in:
parent
bf11676278
commit
c98f1b8b3c
|
|
@ -38,4 +38,7 @@ public interface AffinityGroupDao extends GenericDao<AffinityGroupVO, Long> {
|
|||
AffinityGroupVO findByAccountAndType(Long accountId, String string);
|
||||
|
||||
AffinityGroupVO findDomainLevelGroupByType(Long domainId, String string);
|
||||
|
||||
List<AffinityGroupVO> listByIds(List<Long> ids, boolean exclusive);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import com.cloud.utils.db.SearchBuilder;
|
|||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long> implements AffinityGroupDao {
|
||||
private SearchBuilder<AffinityGroupVO> IdsSearch;
|
||||
private SearchBuilder<AffinityGroupVO> AccountIdSearch;
|
||||
private SearchBuilder<AffinityGroupVO> AccountIdNameSearch;
|
||||
private SearchBuilder<AffinityGroupVO> AccountIdNamesSearch;
|
||||
|
|
@ -47,6 +48,10 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
|
|||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
IdsSearch = createSearchBuilder();
|
||||
IdsSearch.and("idIn", IdsSearch.entity().getId(), SearchCriteria.Op.IN);
|
||||
IdsSearch.done();
|
||||
|
||||
AccountIdSearch = createSearchBuilder();
|
||||
AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AccountIdSearch.done();
|
||||
|
|
@ -158,4 +163,11 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
|
|||
sc.setJoinParameters("domainTypeSearch", "domainId", domainId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AffinityGroupVO> listByIds(List<Long> ids, boolean exclusive) {
|
||||
SearchCriteria<AffinityGroupVO> sc = IdsSearch.create();
|
||||
sc.setParameters("idIn", ids.toArray());
|
||||
return lockRows(sc, null, exclusive);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,14 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionCallbackNoReturn;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
|
@ -56,10 +61,17 @@ public class HostAffinityProcessor extends AffinityProcessorBase implements Affi
|
|||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
List<AffinityGroupVMMapVO> vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType());
|
||||
if (CollectionUtils.isNotEmpty(vmGroupMappings)) {
|
||||
List<Long> affinityGroupIdList = vmGroupMappings.stream().map(AffinityGroupVMMapVO::getAffinityGroupId).collect(Collectors.toList());
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
_affinityGroupDao.listByIds(affinityGroupIdList, true);
|
||||
for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) {
|
||||
processAffinityGroup(vmGroupMapping, plan, vm, vmList);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -132,17 +144,24 @@ public class HostAffinityProcessor extends AffinityProcessorBase implements Affi
|
|||
long plannedHostId = plannedDestination.getHost().getId();
|
||||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
List<AffinityGroupVMMapVO> vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(vmGroupMappings)) {
|
||||
if (CollectionUtils.isEmpty(vmGroupMappings)) {
|
||||
return true;
|
||||
}
|
||||
List<Long> affinityGroupIds = vmGroupMappings.stream().map(AffinityGroupVMMapVO::getAffinityGroupId).collect(Collectors.toList());
|
||||
return Transaction.execute(new TransactionCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(TransactionStatus status) {
|
||||
_affinityGroupDao.listByIds(affinityGroupIds, true);
|
||||
for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) {
|
||||
if (!checkAffinityGroup(vmGroupMapping, vm, plannedHostId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Affinity Group
|
||||
|
|
|
|||
|
|
@ -19,10 +19,17 @@ package org.apache.cloudstack.affinity;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionCallbackNoReturn;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
||||
|
|
@ -36,7 +43,6 @@ import com.cloud.deploy.DeployDestination;
|
|||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.exception.AffinityConflictException;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
|
@ -67,7 +73,23 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements
|
|||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
List<AffinityGroupVMMapVO> vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType());
|
||||
|
||||
if (CollectionUtils.isEmpty(vmGroupMappings)) {
|
||||
return;
|
||||
}
|
||||
List<Long> affinityGroupIds = vmGroupMappings.stream().map(AffinityGroupVMMapVO::getAffinityGroupId).collect(Collectors.toList());
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
_affinityGroupDao.listByIds(affinityGroupIds, true);
|
||||
for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) {
|
||||
processAffinityGroup(vmGroupMapping, avoid, vm);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
protected void processAffinityGroup(AffinityGroupVMMapVO vmGroupMapping, ExcludeList avoid, VirtualMachine vm) {
|
||||
if (vmGroupMapping != null) {
|
||||
AffinityGroupVO group = _affinityGroupDao.findById(vmGroupMapping.getAffinityGroupId());
|
||||
|
||||
|
|
@ -86,6 +108,7 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements
|
|||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Added host " + groupVM.getHostId() + " to avoid set, since VM " + groupVM.getId() + " is present on the host");
|
||||
}
|
||||
}
|
||||
} else if (Arrays.asList(VirtualMachine.State.Starting, VirtualMachine.State.Stopped).contains(groupVM.getState()) && groupVM.getLastHostId() != null) {
|
||||
long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - groupVM.getUpdateTime().getTime()) / 1000;
|
||||
if (secondsSinceLastUpdate < _vmCapacityReleaseInterval) {
|
||||
|
|
@ -99,9 +122,6 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
|
||||
|
|
@ -121,7 +141,15 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements
|
|||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
|
||||
List<AffinityGroupVMMapVO> vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType());
|
||||
if (CollectionUtils.isEmpty(vmGroupMappings)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Long> affinityGroupIds = vmGroupMappings.stream().map(AffinityGroupVMMapVO::getAffinityGroupId).collect(Collectors.toList());
|
||||
return Transaction.execute(new TransactionCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(TransactionStatus status) {
|
||||
_affinityGroupDao.listByIds(affinityGroupIds, true);
|
||||
for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) {
|
||||
// if more than 1 VM's are present in the group then check for
|
||||
// conflict due to parallel deployment
|
||||
|
|
@ -141,5 +169,7 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements
|
|||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue