Redundant virtual router: Try to deploy the second virtual router to different pod/cluster/host/storagepool

The old strategy is to deploy the second virtual router to diffent host only.
This commit is contained in:
Sheng Yang 2011-07-19 12:02:00 -07:00
parent 0449ba6c8c
commit e5e76881c6
4 changed files with 107 additions and 36 deletions

View File

@ -17,12 +17,15 @@
*/
package com.cloud.deploy;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
public class DataCenterDeployment implements DeploymentPlan {
long _dcId;
Long _podId;
Long _clusterId;
Long _poolId;
Long _hostId;
ExcludeList _avoids = null;
boolean _recreateDisks;
public DataCenterDeployment(long dataCenterId) {
@ -61,4 +64,14 @@ public class DataCenterDeployment implements DeploymentPlan {
public Long getPoolId() {
return _poolId;
}
@Override
public ExcludeList getAvoids() {
return _avoids;
}
@Override
public void setAvoids(ExcludeList avoids) {
_avoids = avoids;
}
}

View File

@ -17,6 +17,8 @@
*/
package com.cloud.deploy;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
/**
* Describes how a VM should be deployed.
*/
@ -49,4 +51,16 @@ public interface DeploymentPlan {
* @return pool the VM should be created in; null if no preference.
*/
public Long getPoolId();
/**
* @param avoids
* Set the ExcludeList to avoid for deployment
*/
public void setAvoids(ExcludeList avoids);
/**
* @return
* the ExcludeList to avoid for deployment
*/
public ExcludeList getAvoids();
}

View File

@ -79,6 +79,8 @@ import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
@ -86,6 +88,7 @@ import com.cloud.event.dao.EventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.PermissionDeniedException;
@ -138,6 +141,8 @@ import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.StorageManager;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
@ -283,6 +288,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
VMInstanceDao _instanceDao;
@Inject
NicDao _nicDao;
@Inject
VolumeDao _volumeDao = null;
int _routerRamSize;
int _routerCpuMHz;
@ -904,6 +911,61 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
return routers;
}
private DomainRouterVO startVirtualRouter(DomainRouterVO router, User user, Account caller, Map<Param, Object> params) throws StorageUnavailableException, InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException {
if (router.getRole() == Role.DHCP_USERDATA || !router.getIsRedundantRouter()) {
return this.start(router, user, caller, params, null);
}
DataCenterDeployment plan = new DataCenterDeployment(0, null, null, null, null);
DomainRouterVO result = null;
assert router.getIsRedundantRouter();
List<DomainRouterVO> routerList = _routerDao.findBy(router.getAccountId(), router.getDataCenterIdToDeployIn());
DomainRouterVO routerToBeAvoid = null;
for (DomainRouterVO rrouter : routerList) {
if (rrouter.getHostId() != null && rrouter.getIsRedundantRouter()) {
if (routerToBeAvoid != null) {
throw new ResourceUnavailableException("There are already two redundant routers with IP " + router.getPublicIpAddress(), this.getClass(), 0);
}
routerToBeAvoid = rrouter;
}
}
if (routerToBeAvoid == null) {
return this.start(router, user, caller, params, null);
}
// We would try best to deploy the router to another place
int retryIndex = 5;
ExcludeList[] avoids = new ExcludeList[5];
avoids[0] = new ExcludeList();
avoids[0].addPod(routerToBeAvoid.getPodIdToDeployIn());
avoids[1] = new ExcludeList();
avoids[1].addCluster(_hostDao.findById(routerToBeAvoid.getHostId()).getClusterId());
avoids[2] = new ExcludeList();
avoids[2].addHost(routerToBeAvoid.getHostId());
avoids[3] = new ExcludeList();
List<VolumeVO> volumes = _volumeDao.findByInstanceAndType(routerToBeAvoid.getId(), Type.ROOT);
if (volumes != null && volumes.size() != 0) {
avoids[3].addPool(volumes.get(0).getPoolId());
}
avoids[4] = new ExcludeList();
for (int i = 0; i < retryIndex; i++) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Try to deploy redundant virtual router:" + router.getHostName() + ", for " + i + " time");
}
plan.setAvoids(avoids[i]);
try {
result = this.start(router, user, caller, params, plan);
} catch (InsufficientServerCapacityException ex) {
result = null;
}
if (result != null) {
break;
}
}
return result;
}
@Override
public List<DomainRouterVO> deployVirtualRouter(Network guestNetwork, DeployDestination dest, Account owner, Map<Param, Object> params, boolean isRedundant) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException {
@ -925,11 +987,10 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
for (DomainRouterVO router : routers) {
State state = router.getState();
if (state != State.Running) {
router = this.start(router, _accountService.getSystemUser(), _accountService.getSystemAccount(), params);
router = startVirtualRouter(router, _accountService.getSystemUser(), _accountService.getSystemAccount(), params);
}
runningRouters.add(router);
}
return runningRouters;
}
@ -1032,7 +1093,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
for (DomainRouterVO router : routers) {
State state = router.getState();
if (state != State.Running) {
router = this.start(router, _accountService.getSystemUser(), _accountService.getSystemAccount(), params);
router = startVirtualRouter(router, _accountService.getSystemUser(), _accountService.getSystemAccount(), params);
}
runningRouters.add(router);
}
@ -1413,10 +1474,10 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
return result;
}
private DomainRouterVO start(DomainRouterVO router, User user, Account caller, Map<Param, Object> params) throws StorageUnavailableException, InsufficientCapacityException,
private DomainRouterVO start(DomainRouterVO router, User user, Account caller, Map<Param, Object> params, DeploymentPlan planToDeploy) throws StorageUnavailableException, InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException {
s_logger.debug("Starting router " + router);
if (_itMgr.start(router, params, user, caller) != null) {
if (_itMgr.start(router, params, user, caller, planToDeploy) != null) {
return _routerDao.findById(router.getId());
} else {
return null;
@ -1661,7 +1722,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
} else {
params.put(Param.RestartNetwork, false);
}
return this.start(router, user, account, params);
return startVirtualRouter(router, user, account, params);
}
private void createAssociateIPCommands(final DomainRouterVO router, final List<? extends PublicIpAddress> ips, Commands cmds, long vmId) {

View File

@ -597,7 +597,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), null, null, null);
if(planToDeploy != null){
if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){
if (s_logger.isDebugEnabled()) {
s_logger.debug("advanceStart: DeploymentPlan is provided, using that plan to deploy");
}
@ -609,15 +609,17 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
try {
Journal journal = start.second().getJournal();
ExcludeList avoids = new ExcludeList();
if (vm.getType().equals(VirtualMachine.Type.DomainRouter)) {
List<DomainRouterVO> routers = _routerDao.findBy(vm.getAccountId(), vm.getDataCenterIdToDeployIn());
for (DomainRouterVO router : routers) {
if (router.hostId != null) {
avoids.addHost(router.hostId);
s_logger.info("Router: try to avoid host " + router.hostId);
}
}
ExcludeList avoids = null;
if (planToDeploy != null) {
avoids = planToDeploy.getAvoids();
}
if (avoids == null) {
avoids = new ExcludeList();
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid()
+ ", clusters: " + avoids.getClustersToAvoid()
+ ", hosts: " + avoids.getHostsToAvoid());
}
int retry = _retry;
while (retry-- != 0) { // It's != so that it can match -1.
@ -644,7 +646,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
long rootVolDcId = pool.getDataCenterId();
Long rootVolPodId = pool.getPodId();
Long rootVolClusterId = pool.getClusterId();
if(planToDeploy != null){
if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){
Long clusterIdSpecified = planToDeploy.getClusterId();
if(clusterIdSpecified != null && rootVolClusterId != null){
if(rootVolClusterId.longValue() != clusterIdSpecified.longValue()){
@ -681,26 +683,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
if (dest == null) {
//see if we can allocate the router without limitation
if (vm.getType().equals(VirtualMachine.Type.DomainRouter)) {
avoids = new ExcludeList();
s_logger.info("Router: cancel avoids ");
for (DeploymentPlanner planner : _planners) {
if (planner.canHandle(vmProfile, plan, avoids)) {
dest = planner.plan(vmProfile, plan, avoids);
} else {
continue;
}
if (dest != null) {
avoids.addHost(dest.getHost().getId());
journal.record("Deployment found ", vmProfile, dest);
break;
}
}
}
if (dest == null) {
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
}
}
long destHostId = dest.getHost().getId();