mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-2070: Anti-Affinity - When Vm deployment fails because of not being able to satisfy the anti-affinity rule , user should be provided with more informative message.
Changes: - There is no good mechanism currently to figure out if the deployment failed due to affinity groups only - We can just hint the user that the deployment might have failed due to the affinity groups and ask to review the input
This commit is contained in:
parent
55c1e282e3
commit
31a67706e4
|
|
@ -27,6 +27,8 @@ public class InsufficientServerCapacityException extends InsufficientCapacityExc
|
|||
|
||||
private static final long serialVersionUID = SerialVersionUID.InsufficientServerCapacityException;
|
||||
|
||||
private boolean affinityGroupsApplied = false;
|
||||
|
||||
public InsufficientServerCapacityException(String msg, Long clusterId) {
|
||||
this(msg, Cluster.class, clusterId);
|
||||
}
|
||||
|
|
@ -34,4 +36,13 @@ public class InsufficientServerCapacityException extends InsufficientCapacityExc
|
|||
public InsufficientServerCapacityException(String msg, Class<?> scope, Long id) {
|
||||
super(msg, scope, id);
|
||||
}
|
||||
|
||||
public InsufficientServerCapacityException(String msg, Class<?> scope, Long id, boolean affinityGroupsApplied) {
|
||||
super(msg, scope, id);
|
||||
this.affinityGroupsApplied = affinityGroupsApplied;
|
||||
}
|
||||
|
||||
public boolean isAffinityApplied() {
|
||||
return affinityGroupsApplied;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import com.cloud.dc.DataCenter.NetworkType;
|
|||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
|
|
@ -424,9 +425,15 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
|
|||
s_logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
} catch (InsufficientCapacityException ex) {
|
||||
StringBuilder message = new StringBuilder(ex.getMessage());
|
||||
if (ex instanceof InsufficientServerCapacityException) {
|
||||
if(((InsufficientServerCapacityException)ex).isAffinityApplied()){
|
||||
message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them");
|
||||
}
|
||||
}
|
||||
s_logger.info(ex);
|
||||
s_logger.info(ex.getMessage(), ex);
|
||||
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
|
||||
s_logger.info(message.toString(), ex);
|
||||
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString());
|
||||
}
|
||||
} else {
|
||||
result = _userVmService.getUserVm(getEntityId());
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ import com.cloud.async.AsyncJob;
|
|||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.uservm.UserVm;
|
||||
|
|
@ -112,7 +112,7 @@ public class StartVMCmd extends BaseAsyncCmd {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException {
|
||||
public void execute() throws ResourceUnavailableException, ResourceAllocationException {
|
||||
try {
|
||||
UserContext.current().setEventDetails("Vm Id: " + getId());
|
||||
|
||||
|
|
@ -135,6 +135,16 @@ public class StartVMCmd extends BaseAsyncCmd {
|
|||
} catch (ExecutionException ex) {
|
||||
s_logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
} catch (InsufficientCapacityException ex) {
|
||||
StringBuilder message = new StringBuilder(ex.getMessage());
|
||||
if (ex instanceof InsufficientServerCapacityException) {
|
||||
if (((InsufficientServerCapacityException) ex).isAffinityApplied()) {
|
||||
message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them");
|
||||
}
|
||||
}
|
||||
s_logger.info(ex);
|
||||
s_logger.info(message.toString(), ex);
|
||||
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.UUID;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.db.VMEntityVO;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.db.VMReservationVO;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMEntityDao;
|
||||
|
|
@ -60,6 +61,7 @@ import com.cloud.user.dao.AccountDao;
|
|||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.VirtualMachineProfileImpl;
|
||||
|
|
@ -111,6 +113,9 @@ public class VMEntityManagerImpl implements VMEntityManager {
|
|||
@Inject
|
||||
DeploymentPlanningManager _dpMgr;
|
||||
|
||||
@Inject
|
||||
protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
|
||||
@Override
|
||||
public VMEntityVO loadVirtualMachine(String vmId) {
|
||||
// TODO Auto-generated method stub
|
||||
|
|
@ -123,6 +128,16 @@ public class VMEntityManagerImpl implements VMEntityManager {
|
|||
|
||||
}
|
||||
|
||||
protected boolean areAffinityGroupsAssociated(VirtualMachineProfile<? extends VirtualMachine> vmProfile) {
|
||||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId());
|
||||
|
||||
if (vmGroupCount > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude)
|
||||
throws InsufficientCapacityException, ResourceUnavailableException {
|
||||
|
|
@ -194,7 +209,8 @@ public class VMEntityManagerImpl implements VMEntityManager {
|
|||
// call retry it.
|
||||
return UUID.randomUUID().toString();
|
||||
}else{
|
||||
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
|
||||
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile,
|
||||
DataCenter.class, plan.getDataCenterId(), areAffinityGroupsAssociated(vmProfile));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import javax.ejb.Local;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
|
|
@ -253,6 +254,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
protected ResourceLimitService _resourceLimitMgr;
|
||||
@Inject
|
||||
protected RulesManager rulesMgr;
|
||||
@Inject
|
||||
protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
|
||||
protected List<DeploymentPlanner> _planners;
|
||||
public List<DeploymentPlanner> getPlanners() {
|
||||
|
|
@ -666,6 +669,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean areAffinityGroupsAssociated(VirtualMachineProfile<? extends VirtualMachine> vmProfile) {
|
||||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId());
|
||||
|
||||
if (vmGroupCount > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account) throws InsufficientCapacityException,
|
||||
ConcurrentOperationException, ResourceUnavailableException {
|
||||
|
|
@ -797,7 +810,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
reuseVolume = false;
|
||||
continue;
|
||||
}
|
||||
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
|
||||
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile,
|
||||
DataCenter.class, plan.getDataCenterId(), areAffinityGroupsAssociated(vmProfile));
|
||||
}
|
||||
|
||||
if (dest != null) {
|
||||
|
|
@ -1152,7 +1166,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
|
||||
vmGuru.prepareStop(profile);
|
||||
|
||||
|
||||
StopCommand stop = new StopCommand(vm);
|
||||
boolean stopped = false;
|
||||
StopAnswer answer = null;
|
||||
|
|
@ -2802,7 +2816,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO);
|
||||
|
||||
s_logger.debug("Plugging nic for vm " + vm + " in network " + network);
|
||||
|
||||
|
||||
boolean result = false;
|
||||
try{
|
||||
result = vmGuru.plugNic(network, nicTO, vmTO, context, dest);
|
||||
|
|
@ -2812,17 +2826,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
// insert nic's Id into DB as resource_name
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmVO.getAccountId(),
|
||||
vmVO.getDataCenterId(), vmVO.getId(), Long.toString(nic.getId()), nic.getNetworkId(),
|
||||
null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid());
|
||||
null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid());
|
||||
return nic;
|
||||
} else {
|
||||
s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
if(!result){
|
||||
_networkMgr.removeNic(vmProfile, _nicsDao.findById(nic.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (vm.getState() == State.Stopped) {
|
||||
//1) allocate nic
|
||||
return _networkMgr.createNicForVm(network, requested, context, vmProfile, false);
|
||||
|
|
@ -2863,10 +2877,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
|
||||
throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
|
||||
}
|
||||
|
||||
|
||||
// if specified nic is associated with PF/LB/Static NAT
|
||||
if(rulesMgr.listAssociatedRulesForGuestNic(nic).size() > 0){
|
||||
throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network
|
||||
throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network
|
||||
+ ", nic has associated Port forwarding or Load balancer or Static NAT rules.");
|
||||
}
|
||||
|
||||
|
|
@ -2884,7 +2898,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
|
||||
long isDefault = (nic.isDefaultNic()) ? 1 : 0;
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(),
|
||||
vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null,
|
||||
vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null,
|
||||
isDefault, VirtualMachine.class.getName(), vm.getUuid());
|
||||
} else {
|
||||
s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
|
||||
|
|
|
|||
Loading…
Reference in New Issue