diff --git a/api/src/com/cloud/deploy/DataCenterDeployment.java b/api/src/com/cloud/deploy/DataCenterDeployment.java
index cac3839999d..5be0247c2fc 100644
--- a/api/src/com/cloud/deploy/DataCenterDeployment.java
+++ b/api/src/com/cloud/deploy/DataCenterDeployment.java
@@ -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;
+ }
}
diff --git a/api/src/com/cloud/deploy/DeploymentPlan.java b/api/src/com/cloud/deploy/DeploymentPlan.java
index 894bca77d25..0881f7bd50c 100644
--- a/api/src/com/cloud/deploy/DeploymentPlan.java
+++ b/api/src/com/cloud/deploy/DeploymentPlan.java
@@ -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();
}
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 2339e819536..5ebc7ac5f8d 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -77,6 +77,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;
@@ -84,6 +86,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;
@@ -131,6 +134,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;
@@ -270,6 +275,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
VMInstanceDao _instanceDao;
@Inject
NicDao _nicDao;
+ @Inject
+ VolumeDao _volumeDao = null;
int _routerRamSize;
int _routerCpuMHz;
@@ -891,6 +898,61 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
return routers;
}
+ private DomainRouterVO startVirtualRouter(DomainRouterVO router, User user, Account caller, Map 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 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 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 deployVirtualRouter(Network guestNetwork, DeployDestination dest, Account owner, Map params, boolean isRedundant) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException {
@@ -912,11 +974,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;
}
@@ -1019,7 +1080,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);
}
@@ -1316,10 +1377,10 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
public void finalizeExpunge(DomainRouterVO vm) {
}
- private DomainRouterVO start(DomainRouterVO router, User user, Account caller, Map params) throws StorageUnavailableException, InsufficientCapacityException,
+ private DomainRouterVO start(DomainRouterVO router, User user, Account caller, Map 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;
@@ -1512,7 +1573,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) {
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 939d7dbb6b1..faa2e0c796c 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -600,7 +600,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");
}
@@ -612,15 +612,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 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.
@@ -647,7 +649,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()){
@@ -684,26 +686,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();