diff --git a/api/src/com/cloud/resource/ResourceService.java b/api/src/com/cloud/resource/ResourceService.java index d8917ed7033..3cd544f4d5d 100755 --- a/api/src/com/cloud/resource/ResourceService.java +++ b/api/src/com/cloud/resource/ResourceService.java @@ -92,7 +92,7 @@ public interface ResourceService { Swift discoverSwift(AddSwiftCmd addSwiftCmd) throws DiscoveryException; - List getSupportedHypervisorTypes(long zoneId); + List getSupportedHypervisorTypes(long zoneId, boolean forVirtualRouter, Long podId); List listSwifts(ListSwiftsCmd cmd); } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 831bbb13f9d..42b5d9bca22 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1149,7 +1149,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian /* * Ovm won't support any system. So we have to choose a partner cluster in the same pod to start domain router for us */ - private HypervisorType getAClusterToStartDomainRouterForOvm(long podId) { + private HypervisorType getClusterToStartDomainRouterForOvm(long podId) { List clusters = _clusterDao.listByPodId(podId); for (ClusterVO cv : clusters) { if (cv.getHypervisorType() == HypervisorType.Ovm || cv.getHypervisorType() == HypervisorType.BareMetal) { @@ -1176,7 +1176,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } @DB - protected List findOrCreateVirtualRouters(Network guestNetwork, DeployDestination dest, Account owner, boolean isRedundant) throws ConcurrentOperationException, InsufficientCapacityException { + protected List findOrDeployVirtualRouters(Network guestNetwork, DeployDestination dest, Account owner, boolean isRedundant, Map params) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { Network network = _networkDao.acquireInLockTable(guestNetwork.getId()); if (network == null) { @@ -1195,11 +1195,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian return null; } List routers; + Long podId = null; if (publicNetwork) { routers = _routerDao.listByNetworkAndRole(guestNetwork.getId(), Role.VIRTUAL_ROUTER); } else { if (isPodBased) { - Long podId = dest.getPod().getId(); + podId = dest.getPod().getId(); routers = _routerDao.listByNetworkAndPodAndRole(guestNetwork.getId(), podId, Role.VIRTUAL_ROUTER); plan = new DataCenterDeployment(dcId, podId, null, null, null, null); } else { @@ -1314,11 +1315,27 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian //Router is the network element, we don't know the hypervisor type yet. //Try to allocate the domR twice using diff hypervisors, and when failed both times, throw the exception up - List supportedHypervisors = _resourceMgr.getSupportedHypervisorTypes(dest.getDataCenter().getId()); + List supportedHypervisors = new ArrayList(); + + if (dest.getCluster() != null) { + if (dest.getCluster().getHypervisorType() == HypervisorType.Ovm) { + supportedHypervisors.add(getClusterToStartDomainRouterForOvm(dest.getCluster().getPodId())); + } else { + supportedHypervisors.add(dest.getCluster().getHypervisorType()); + } + } else { + supportedHypervisors = _resourceMgr.getSupportedHypervisorTypes(dest.getDataCenter().getId(), true, podId); + } + if (supportedHypervisors.isEmpty()) { + if (podId != null) { + throw new InsufficientServerCapacityException("Unable to create virtual router, there are no clusters in the pod ", Pod.class, podId); + } throw new InsufficientServerCapacityException("Unable to create virtual router, there are no clusters in the zone ", DataCenter.class, dest.getDataCenter().getId()); } - int retry = 0; + + int allocateRetry = 0; + int startRetry = 0; for (HypervisorType hType : supportedHypervisors) { try { s_logger.debug("Allocating the domR with the hypervisor type " + hType); @@ -1339,17 +1356,34 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestNetwork.getId(), isRedundant, 0, false, RedundantState.UNKNOWN, offerHA, false); router.setRole(Role.VIRTUAL_ROUTER); router = _itMgr.allocate(router, template, routerOffering, networks, plan, null, owner); - break; } catch (InsufficientCapacityException ex) { - if (retry < 2) { + if (allocateRetry < 2) { s_logger.debug("Failed to allocate the domR with hypervisor type " + hType + ", retrying one more time"); + continue; } else { throw ex; } } finally { - retry++; + allocateRetry++; + } + + try { + router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params); + break; + } catch (InsufficientCapacityException ex) { + if (startRetry < 2) { + s_logger.debug("Failed to start the domR " + router + " with hypervisor type " + hType + ", destroying it and recreating one more time"); + //destroy the router + destroyRouter(router.getId()); + continue; + } else { + throw ex; + } + } finally { + startRetry++; } } + routers.add(router); // Creating stats entry for router @@ -1373,7 +1407,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian private DomainRouterVO startVirtualRouter(DomainRouterVO router, User user, Account caller, Map params) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - if (router.getRole() != Role.VIRTUAL_ROUTER || !router.getIsRedundantRouter()) { + + if (router.getRole() != Role.VIRTUAL_ROUTER || !router.getIsRedundantRouter()) { return this.start(router, user, caller, params, null); } @@ -1451,7 +1486,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian + guestNetwork; assert guestNetwork.getTrafficType() == TrafficType.Guest; - List routers = findOrCreateVirtualRouters(guestNetwork, dest, owner, isRedundant); + List routers = findOrDeployVirtualRouters(guestNetwork, dest, owner, isRedundant, params); List runningRouters = null; if (routers != null) { diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index add6d645add..85928d7c2ff 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -1218,12 +1218,21 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } @Override - public List getSupportedHypervisorTypes(long zoneId) { + public List getSupportedHypervisorTypes(long zoneId, boolean forVirtualRouter, Long podId) { List hypervisorTypes = new ArrayList(); - List clustersForZone = _clusterDao.listByZoneId(zoneId); + List clustersForZone = new ArrayList(); + if (podId != null) { + clustersForZone = _clusterDao.listByPodId(podId); + } else { + clustersForZone = _clusterDao.listByZoneId(zoneId); + } + for (ClusterVO cluster : clustersForZone) { - hypervisorTypes.add(cluster.getHypervisorType()); + HypervisorType hType = cluster.getHypervisorType(); + if (!forVirtualRouter || (forVirtualRouter && hType != HypervisorType.BareMetal && hType != HypervisorType.Ovm)) { + hypervisorTypes.add(hType); + } } return hypervisorTypes;