From 6dd5c3fd42c70855d75156243dddc4933436baaf Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 11 Oct 2012 18:30:00 +0530 Subject: [PATCH] CLOUDSTACK-70: Improve restart network behaviour for basic network If cleanup=true, network elements and resources are shutdown and reimplemented. Else, shutdown/reimplementation is skipped. Enabled cleanup checkbox in CS UI. For both cases, VRs are only deployed for Pods with no running or starting VRs and Pods having running or starting user vms. New DAO helpers introduced: HostPodDao: listByDataCenterIdVMTypeAndStates DomainRouterDao: listByPodId and listByPodIdAndStates VMInstanceDao: listByPodId and corrected definition of listByTypeAndState Signed-off-by: Rohit Yadav --- server/src/com/cloud/dc/dao/HostPodDao.java | 7 +- .../src/com/cloud/dc/dao/HostPodDaoImpl.java | 28 +++- .../com/cloud/network/NetworkManagerImpl.java | 10 -- .../VirtualNetworkApplianceManagerImpl.java | 155 +++++++++++------- .../src/com/cloud/vm/dao/DomainRouterDao.java | 19 ++- .../com/cloud/vm/dao/DomainRouterDaoImpl.java | 17 ++ .../src/com/cloud/vm/dao/VMInstanceDao.java | 13 +- .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 12 +- ui/scripts/network.js | 12 +- 9 files changed, 185 insertions(+), 88 deletions(-) diff --git a/server/src/com/cloud/dc/dao/HostPodDao.java b/server/src/com/cloud/dc/dao/HostPodDao.java index f031ac977e8..ced348425fd 100644 --- a/server/src/com/cloud/dc/dao/HostPodDao.java +++ b/server/src/com/cloud/dc/dao/HostPodDao.java @@ -21,11 +21,14 @@ import java.util.List; import com.cloud.dc.HostPodVO; import com.cloud.utils.db.GenericDao; +import com.cloud.vm.VirtualMachine; public interface HostPodDao extends GenericDao { public List listByDataCenterId(long id); - - public HostPodVO findByName(String name, long dcId); + + public List listByDataCenterIdVMTypeAndStates(long id, VirtualMachine.Type type, VirtualMachine.State... states); + + public HostPodVO findByName(String name, long dcId); public HashMap> getCurrentPodCidrSubnets(long zoneId, long podIdToSkip); diff --git a/server/src/com/cloud/dc/dao/HostPodDaoImpl.java b/server/src/com/cloud/dc/dao/HostPodDaoImpl.java index bec8c518cdf..fce308aaa77 100644 --- a/server/src/com/cloud/dc/dao/HostPodDaoImpl.java +++ b/server/src/com/cloud/dc/dao/HostPodDaoImpl.java @@ -31,10 +31,15 @@ import com.cloud.dc.HostPodVO; import com.cloud.org.Grouping; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.VMInstanceDaoImpl; @Local(value={HostPodDao.class}) public class HostPodDaoImpl extends GenericDaoBase implements HostPodDao { @@ -61,7 +66,28 @@ public class HostPodDaoImpl extends GenericDaoBase implements H return listBy(sc); } - + + @Override + public List listByDataCenterIdVMTypeAndStates(long id, VirtualMachine.Type type, VirtualMachine.State... states) { + final VMInstanceDaoImpl _vmDao = ComponentLocator.inject(VMInstanceDaoImpl.class); + SearchBuilder vmInstanceSearch = _vmDao.createSearchBuilder(); + vmInstanceSearch.and("type", vmInstanceSearch.entity().getType(), SearchCriteria.Op.EQ); + vmInstanceSearch.and("states", vmInstanceSearch.entity().getState(), SearchCriteria.Op.IN); + + SearchBuilder podIdSearch = createSearchBuilder(); + podIdSearch.and("dc", podIdSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + podIdSearch.select(null, SearchCriteria.Func.DISTINCT, podIdSearch.entity().getId()); + podIdSearch.join("vmInstanceSearch", vmInstanceSearch, podIdSearch.entity().getId(), + vmInstanceSearch.entity().getPodIdToDeployIn(), JoinBuilder.JoinType.INNER); + podIdSearch.done(); + + SearchCriteria sc = podIdSearch.create(); + sc.setParameters("dc", id); + sc.setJoinParameters("vmInstanceSearch", "type", type); + sc.setJoinParameters("vmInstanceSearch", "states", (Object[]) states); + return listBy(sc); + } + @Override public HostPodVO findByName(String name, long dcId) { SearchCriteria sc = DataCenterAndNameSearch.create(); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 7b38c836466..13a2bb1cbd1 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -3807,12 +3807,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Network is not in the right state to be restarted. Correct states are: " + Network.State.Implemented + ", " + Network.State.Setup); } - // don't allow clenaup=true for the network in Basic zone - DataCenter zone = _configMgr.getZone(network.getDataCenterId()); - if (zone.getNetworkType() == NetworkType.Basic && cleanup) { - throw new InvalidParameterValueException("Cleanup can't be true when restart network in Basic zone"); - } - _accountMgr.checkAccess(callerAccount, null, true, network); boolean success = restartNetwork(networkId, callerAccount, callerUser, cleanup); @@ -3857,10 +3851,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount); if (cleanup) { - if (network.getGuestType() != GuestType.Isolated) { - s_logger.warn("Only support clean up network for isolated network!"); - return false; - } // shutdown the network s_logger.debug("Shutting down the network id=" + networkId + " as a part of network restart"); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 4400a9b52ad..dcb630e2895 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1263,7 +1263,6 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian boolean isRedundant, Map params) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - List routers = new ArrayList(); Network lock = _networkDao.acquireInLockTable(guestNetwork.getId(), _networkMgr.getNetworkLockTimeout()); if (lock == null) { @@ -1285,73 +1284,111 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic || _networkMgr.areServicesSupportedInNetwork(guestNetwork.getId(), Service.SecurityGroup)) && guestNetwork.getTrafficType() == TrafficType.Guest; - - Pair> planAndRouters = getDeploymentPlanAndRouters(isPodBased, dest, guestNetwork.getId()); - routers = planAndRouters.second(); - - // 2) Figure out required routers count - int routerCount = 1; - if (isRedundant) { - routerCount = 2; + + // dest has pod=null, for Basic Zone findOrDeployVRs for all Pods + List destinations = new ArrayList(); + + if (dest.getDataCenter().getNetworkType() == NetworkType.Basic) { + // Find all pods in the data center with running or starting user vms + long dcId = dest.getDataCenter().getId(); + List pods = _podDao.listByDataCenterIdVMTypeAndStates(dcId, VirtualMachine.Type.User, VirtualMachine.State.Starting, VirtualMachine.State.Running); + + // Loop through all the pods skip those with running or starting VRs + for (HostPodVO pod: pods) { + // Get list of VRs in starting or running state + long podId = pod.getId(); + List virtualRouters = _routerDao.listByPodIdAndStates(podId, VirtualMachine.State.Starting, VirtualMachine.State.Running); + + assert (virtualRouters.size() <= 1) : "Pod can have utmost one VR in Basic Zone, please check!"; + + // Add virtualRouters to the routers, this avoids the situation when + // all routers are skipped and VirtualRouterElement throws exception + routers.addAll(virtualRouters); + + // If List size is one, we already have a starting or running VR, skip deployment + if (virtualRouters.size() == 1) { + s_logger.debug("Skipping VR deployment: Found a running or starting VR in Pod " + + pod.getName() + " id=" + podId); + continue; + } + // Add new DeployDestination for this pod + destinations.add(new DeployDestination(dest.getDataCenter(), pod, null, null)); + } } - - /* If old network is redundant but new is single router, then routers.size() = 2 but routerCount = 1 */ - if (routers.size() >= routerCount) { - return routers; - } - - if (routers.size() >= 5) { - s_logger.error("Too much redundant routers!"); + else { + // Else, just add the supplied dest + destinations.add(dest); } - // Check if providers are supported in the physical networks - VirtualRouterProviderType type = VirtualRouterProviderType.VirtualRouter; - Long physicalNetworkId = _networkMgr.getPhysicalNetworkId(guestNetwork); - PhysicalNetworkServiceProvider provider = _physicalProviderDao.findByServiceProvider(physicalNetworkId, type.toString()); - if (provider == null) { - throw new CloudRuntimeException("Cannot find service provider " + type.toString() + " in physical network " + physicalNetworkId); - } - VirtualRouterProvider vrProvider = _vrProviderDao.findByNspIdAndType(provider.getId(), type); - if (vrProvider == null) { - throw new CloudRuntimeException("Cannot find virtual router provider " + type.toString()+ " as service provider " + provider.getId()); - } + // Except for Basic Zone, the for loop will iterate only once + for (DeployDestination destination: destinations) { + Pair> planAndRouters = getDeploymentPlanAndRouters(isPodBased, destination, guestNetwork.getId()); + routers = planAndRouters.second(); - if (_networkMgr.isNetworkSystem(guestNetwork) || guestNetwork.getGuestType() == Network.GuestType.Shared) { - owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM); - } + // 2) Figure out required routers count + int routerCount = 1; + if (isRedundant) { + routerCount = 2; + } - //Check if public network has to be set on VR - boolean publicNetwork = false; - if (_networkMgr.isProviderSupportServiceInNetwork(guestNetwork.getId(), Service.SourceNat, Provider.VirtualRouter)) { - publicNetwork = true; - } - if (isRedundant && !publicNetwork) { - s_logger.error("Didn't support redundant virtual router without public network!"); - return null; - } + // If old network is redundant but new is single router, then routers.size() = 2 but routerCount = 1 + if (routers.size() >= routerCount) { + return routers; + } - Long offeringId = _networkOfferingDao.findById(guestNetwork.getNetworkOfferingId()).getServiceOfferingId(); - if (offeringId == null) { - offeringId = _offering.getId(); - } + if (routers.size() >= 5) { + s_logger.error("Too much redundant routers!"); + } - PublicIp sourceNatIp = null; - if (publicNetwork) { - sourceNatIp = _networkMgr.assignSourceNatIpAddressToGuestNetwork(owner, guestNetwork); - } + // Check if providers are supported in the physical networks + VirtualRouterProviderType type = VirtualRouterProviderType.VirtualRouter; + Long physicalNetworkId = _networkMgr.getPhysicalNetworkId(guestNetwork); + PhysicalNetworkServiceProvider provider = _physicalProviderDao.findByServiceProvider(physicalNetworkId, type.toString()); + if (provider == null) { + throw new CloudRuntimeException("Cannot find service provider " + type.toString() + " in physical network " + physicalNetworkId); + } + VirtualRouterProvider vrProvider = _vrProviderDao.findByNspIdAndType(provider.getId(), type); + if (vrProvider == null) { + throw new CloudRuntimeException("Cannot find virtual router provider " + type.toString() + " as service provider " + provider.getId()); + } - //3) deploy virtual router(s) - int count = routerCount - routers.size(); - DeploymentPlan plan = planAndRouters.first(); - for (int i = 0; i < count; i++) { - List> networks = createRouterNetworks(owner, isRedundant, plan, guestNetwork, - new Pair(publicNetwork, sourceNatIp)); - //don't start the router as we are holding the network lock that needs to be released at the end of router allocation - DomainRouterVO router = deployRouter(owner, dest, plan, params, isRedundant, vrProvider, offeringId, - null, networks, false, null); + if (_networkMgr.isNetworkSystem(guestNetwork) || guestNetwork.getGuestType() == Network.GuestType.Shared) { + owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM); + } - _routerDao.addRouterToGuestNetwork(router, guestNetwork); - routers.add(router); + // Check if public network has to be set on VR + boolean publicNetwork = false; + if (_networkMgr.isProviderSupportServiceInNetwork(guestNetwork.getId(), Service.SourceNat, Provider.VirtualRouter)) { + publicNetwork = true; + } + if (isRedundant && !publicNetwork) { + s_logger.error("Didn't support redundant virtual router without public network!"); + return null; + } + + Long offeringId = _networkOfferingDao.findById(guestNetwork.getNetworkOfferingId()).getServiceOfferingId(); + if (offeringId == null) { + offeringId = _offering.getId(); + } + + PublicIp sourceNatIp = null; + if (publicNetwork) { + sourceNatIp = _networkMgr.assignSourceNatIpAddressToGuestNetwork(owner, guestNetwork); + } + + // 3) deploy virtual router(s) + int count = routerCount - routers.size(); + DeploymentPlan plan = planAndRouters.first(); + for (int i = 0; i < count; i++) { + List> networks = createRouterNetworks(owner, isRedundant, plan, guestNetwork, + new Pair(publicNetwork, sourceNatIp)); + //don't start the router as we are holding the network lock that needs to be released at the end of router allocation + DomainRouterVO router = deployRouter(owner, destination, plan, params, isRedundant, vrProvider, offeringId, + null, networks, false, null); + + _routerDao.addRouterToGuestNetwork(router, guestNetwork); + routers.add(router); + } } } finally { if (lock != null) { diff --git a/server/src/com/cloud/vm/dao/DomainRouterDao.java b/server/src/com/cloud/vm/dao/DomainRouterDao.java index 01e32588007..95d1ea6ca14 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDao.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDao.java @@ -61,7 +61,24 @@ public interface DomainRouterDao extends GenericDao { */ public List listByHostId(Long hostId); public List listByLastHostId(Long hostId); - + + /** + * list virtual machine routers by pod id. pass in null to get all + * virtual machine routers. + * @param podId id of the pod. null if to get all. + * @return list of DomainRouterVO + */ + public List listByPodId(Long podId); + + /** + * list virtual machine routers by pod id. pass in null to get all + * virtual machine routers. + * @param podId id of the pod. null if to get all. + * @param state state of the domain router. null if to get all. + * @return list of DomainRouterVO + */ + public List listByPodIdAndStates(Long podId, State... states); + /** * list virtual machine routers by host id. * pass in null to get all diff --git a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java index 175d3f28d04..9ab3ad0f465 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -41,6 +41,7 @@ import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; import com.cloud.utils.db.UpdateBuilder; import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; @Local(value = { DomainRouterDao.class }) @@ -66,6 +67,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase im AllFieldsSearch.and("host", AllFieldsSearch.entity().getHostId(), Op.EQ); AllFieldsSearch.and("lastHost", AllFieldsSearch.entity().getLastHostId(), Op.EQ); AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); + AllFieldsSearch.and("states", AllFieldsSearch.entity().getState(), Op.IN); SearchBuilder joinRouterNetwork = _routerNetworkDao.createSearchBuilder(); joinRouterNetwork.and("networkId", joinRouterNetwork.entity().getNetworkId(), Op.EQ); AllFieldsSearch.join("networkRouter", joinRouterNetwork, joinRouterNetwork.entity().getRouterId(), AllFieldsSearch.entity().getId(), JoinType.INNER); @@ -177,6 +179,21 @@ public class DomainRouterDaoImpl extends GenericDaoBase im return listBy(sc); } + @Override + public List listByPodId(Long podId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("podId", podId); + return listBy(sc); + } + + @Override + public List listByPodIdAndStates(Long podId, State... states) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("podId", podId); + sc.setParameters("states", (Object[]) states); + return listBy(sc); + } + @Override public List listIsolatedByHostId(Long hostId) { SearchCriteria sc = HostUpSearch.create(); diff --git a/server/src/com/cloud/vm/dao/VMInstanceDao.java b/server/src/com/cloud/vm/dao/VMInstanceDao.java index 2cf3d75018c..8b0a523f56c 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDao.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDao.java @@ -46,7 +46,14 @@ public interface VMInstanceDao extends GenericDao, StateDao< * @return list of VMInstanceVO in the specified zone */ List listByZoneId(long zoneId); - + + /** + * List VMs by pod ID + * @param podId + * @return list of VMInstanceVO in the specified pod + */ + List listByPodId(long podId); + /** * Lists non-expunged VMs by zone ID and templateId * @param zoneId @@ -76,8 +83,8 @@ public interface VMInstanceDao extends GenericDao, StateDao< List listByZoneIdAndType(long zoneId, VirtualMachine.Type type); List listUpByHostId(Long hostId); List listByLastHostId(Long hostId); - - List listByTypeAndState(State state, VirtualMachine.Type type); + + List listByTypeAndState(VirtualMachine.Type type, State state); List listByAccountId(long accountId); public Long countAllocatedVirtualRoutersForAccount(long accountId); diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 571b5d1841c..85ad5d02e87 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -230,14 +230,20 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem return listBy(sc); } - + + @Override + public List listByPodId(long podId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("pod", podId); + return listBy(sc); + } + @Override public List listByClusterId(long clusterId) { SearchCriteria sc = VMClusterSearch.create(); sc.setJoinParameters("hostSearch", "clusterId", clusterId); return listBy(sc); } - @Override public List listLHByClusterId(long clusterId) { @@ -309,7 +315,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem } @Override - public List listByTypeAndState(State state, VirtualMachine.Type type) { + public List listByTypeAndState(VirtualMachine.Type type, State state) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("type", type); sc.setParameters("state", state); diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 65adf666cb6..d3912a0dd4e 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -699,15 +699,9 @@ success: function(json){ zoneObj = json.listzonesresponse.zone[0]; } - }); - if(zoneObj.networktype == "Basic") { - args.$form.find('.form-item[rel=cleanup]').find('input').removeAttr('checked'); //unchecked - args.$form.find('.form-item[rel=cleanup]').hide(); //hidden - } - else { - args.$form.find('.form-item[rel=cleanup]').find('input').attr('checked', 'checked'); //checked - args.$form.find('.form-item[rel=cleanup]').css('display', 'inline-block'); //shown - } + }); + args.$form.find('.form-item[rel=cleanup]').find('input').attr('checked', 'checked'); //checked + args.$form.find('.form-item[rel=cleanup]').css('display', 'inline-block'); //shown }, fields: { cleanup: {