diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index f2c4de520a1..741a687a1f7 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -110,4 +110,7 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, boolean getSpecifyIpRanges(); boolean isInline(); + + boolean getIsPersistent(); + } diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index f704aec734a..d8951917c1f 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -103,6 +103,7 @@ public class ApiConstants { public static final String IS_EXTRACTABLE = "isextractable"; public static final String IS_FEATURED = "isfeatured"; public static final String IS_PUBLIC = "ispublic"; + public static final String IS_PERSISTENT = "ispersistent"; public static final String IS_READY = "isready"; public static final String IS_RECURSIVE = "isrecursive"; public static final String ISO_FILTER = "isofilter"; diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java index 9d3ceb828e1..abd1d3b9af6 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java @@ -88,6 +88,9 @@ public class CreateNetworkOfferingCmd extends BaseCmd { @Parameter(name=ApiConstants.SPECIFY_IP_RANGES, type=CommandType.BOOLEAN, description="true if network offering supports specifying ip ranges; defaulted to false if not specified") private Boolean specifyIpRanges; + @Parameter(name=ApiConstants.IS_PERSISTENT, type=CommandType.BOOLEAN, description="true if network offering supports persistent networks; defaulted to false if not specified") + private Boolean isPersistent; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -147,6 +150,10 @@ public class CreateNetworkOfferingCmd extends BaseCmd { return conserveMode; } + public Boolean getIsPersistent() { + return isPersistent == null ? false : isPersistent; + } + public Map> getServiceProviders() { Map> serviceProviderMap = null; if (serviceProviderList != null && !serviceProviderList.isEmpty()) { diff --git a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java index 5c1479105f8..b83b29b0563 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java @@ -80,6 +80,8 @@ public class NetworkOfferingResponse extends BaseResponse { @SerializedName(ApiConstants.FOR_VPC) @Param(description="true if network offering can be used by VPC networks only") private Boolean forVpc; + @SerializedName(ApiConstants.IS_PERSISTENT) @Param(description="true if network offering supports persistent networks, false otherwise") + private Boolean isPersistent; public void setId(String id) { this.id = id; @@ -149,4 +151,9 @@ public class NetworkOfferingResponse extends BaseResponse { public void setForVpc(Boolean forVpc) { this.forVpc = forVpc; } + + public void setIsPersistent(Boolean isPersistent) { + this.isPersistent = isPersistent; + } + } diff --git a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java index ba8ea3277e7..40d68509868 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java @@ -141,6 +141,9 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes @SerializedName(ApiConstants.CAN_USE_FOR_DEPLOY) @Param(description="list networks available for vm deployment") private Boolean canUseForDeploy; + @SerializedName(ApiConstants.IS_PERSISTENT) @Param(description="list networks that are persistent") + private Boolean isPersistent; + @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with network", responseObject = ResourceTagResponse.class) private List tags; @@ -301,6 +304,10 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes this.canUseForDeploy = canUseForDeploy; } + public void setIsPersistent(Boolean isPersistent) { + this.isPersistent = isPersistent; + } + public void setTags(List tags) { this.tags = tags; } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 0ae4f0fae80..2dcd09c897a 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -1901,6 +1901,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setConserveMode(offering.isConserveMode()); response.setSpecifyIpRanges(offering.getSpecifyIpRanges()); response.setAvailability(offering.getAvailability().toString()); + response.setIsPersistent(offering.getIsPersistent()); response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId())); Long so = null; if (offering.getServiceOfferingId() != null) { @@ -2053,6 +2054,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setNetworkOfferingDisplayText(networkOffering.getDisplayText()); response.setIsSystem(networkOffering.isSystemOnly()); response.setNetworkOfferingAvailability(networkOffering.getAvailability().toString()); + response.setIsPersistent(networkOffering.getIsPersistent()); } if (network.getAclType() != null) { diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index 09e8ac902b9..5c1b0d58c6f 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -173,6 +173,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { * @param trafficType * @param tags * @param specifyVlan + * @param isPersistent * ; * @param networkRate * TODO @@ -196,7 +197,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability, Integer networkRate, Map> serviceProviderMap, boolean isDefault, Network.GuestType type, boolean systemOnly, Long serviceOfferingId, boolean conserveMode, Map> serviceCapabilityMap, - boolean specifyIpRanges); + boolean specifyIpRanges, boolean isPersistent); Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException; diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index c8acf3b1caa..944344731a3 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2995,6 +2995,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura Availability availability = null; Network.GuestType guestType = null; boolean specifyIpRanges = cmd.getSpecifyIpRanges(); + boolean isPersistent = cmd.getIsPersistent(); // Verify traffic type for (TrafficType tType : TrafficType.values()) { @@ -3165,7 +3166,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } return createNetworkOffering(name, displayText, trafficType, tags, specifyVlan, availability, networkRate, serviceProviderMap, false, guestType, false, - serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges); + serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges, isPersistent); } void validateLoadBalancerServiceCapabilities(Map lbServiceCapabilityMap) { @@ -3253,7 +3254,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura @DB public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability, Integer networkRate, Map> serviceProviderMap, boolean isDefault, Network.GuestType type, boolean systemOnly, Long serviceOfferingId, - boolean conserveMode, Map> serviceCapabilityMap, boolean specifyIpRanges) { + boolean conserveMode, Map> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent) { String multicastRateStr = _configDao.getValue("multicast.throttling.rate"); int multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr)); @@ -3274,6 +3275,11 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura + type + " and service " + Service.SourceNat.getName() + " is supported"); } + // isPersistent should always be false for Shared network Offerings + if (isPersistent && type == GuestType.Shared) { + throw new InvalidParameterValueException("isPersistent should be false if network offering's type is " + type); + } + // validate availability value if (availability == NetworkOffering.Availability.Required) { boolean canOffBeRequired = (type == GuestType.Isolated && serviceProviderMap.containsKey(Service.SourceNat)); @@ -3352,7 +3358,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb, - sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline); + sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent); if (serviceOfferingId != null) { offering.setServiceOfferingId(serviceOfferingId); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 218583b0000..6fe810ef644 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -77,6 +77,8 @@ import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.org.Grouping; import com.cloud.user.*; import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.UserDao; +import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.component.Adapters; @@ -127,6 +129,8 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { @Inject DomainDao _domainDao = null; @Inject + UserDao _userDao = null; + @Inject ConfigurationDao _configDao; @Inject UserVmDao _userVmDao = null; @@ -856,14 +860,14 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { NetworkOfferingVO offering = null; if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOfferingWithSGService) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOfferingWithSGService, "Offering for Shared Security group enabled networks", TrafficType.Guest, null, - true, Availability.Optional, null, defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, null, true); + true, Availability.Optional, null, defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, null, true, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOffering) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOffering, "Offering for Shared networks", TrafficType.Guest, null, true, Availability.Optional, null, - defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, null, true); + defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, null, true, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } @@ -886,7 +890,7 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService, "Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest, null, false, Availability.Required, null, defaultINetworkOfferingProvidersForVpcNetwork, - true, Network.GuestType.Isolated, false, null, true, null, false); + true, Network.GuestType.Isolated, false, null, true, null, false, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } @@ -895,7 +899,7 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks, "Offering for Isolated VPC networks with Source Nat service enabled", TrafficType.Guest, null, false, Availability.Optional, null, defaultVPCOffProviders, - true, Network.GuestType.Isolated, false, null, false, null, false); + true, Network.GuestType.Isolated, false, null, false, null, false, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } @@ -906,7 +910,7 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB, "Offering for Isolated VPC networks with Source Nat service enabled and LB service disabled", TrafficType.Guest, null, false, Availability.Optional, null, defaultVPCOffProviders, - true, Network.GuestType.Isolated, false, null, false, null, false); + true, Network.GuestType.Isolated, false, null, false, null, false, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } @@ -915,7 +919,7 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOffering, "Offering for Isolated networks with no Source Nat service", TrafficType.Guest, null, true, Availability.Optional, null, defaultIsolatedNetworkOfferingProviders, true, Network.GuestType.Isolated, - false, null, true, null, true); + false, null, true, null, true, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } @@ -944,7 +948,7 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedEIPandELBNetworkOffering) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, null, true, - Availability.Optional, null, netscalerServiceProviders, true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap, true); + Availability.Optional, null, netscalerServiceProviders, true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap, true, false); offering.setState(NetworkOffering.State.Enabled); offering.setDedicatedLB(false); _networkOfferingDao.update(offering.getId(), offering); @@ -1999,8 +2003,6 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { return network; } - - @Override @DB public boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements) { @@ -2533,14 +2535,13 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { } // create new Virtual network (Isolated with SourceNAT) for the user if it doesn't exist + List requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false); + if (requiredOfferings.size() < 1) { + throw new CloudRuntimeException("Unable to find network offering with availability=" + + Availability.Required + " to automatically create the network as part of createVlanIpRange"); + } if (createNetwork) { - List requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false); - if (requiredOfferings.size() < 1) { - throw new CloudRuntimeException("Unable to find network offering with availability=" + - Availability.Required + " to automatically create the network as part of createVlanIpRange"); - } if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) { - long physicalNetworkId = _networkModel.findPhysicalNetworkId(zoneId, requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType()); // Validate physical network PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); @@ -2595,6 +2596,31 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener { } txn.commit(); + + // if the network offering has persistent set to true, implement the network + if ( createNetwork && requiredOfferings.get(0).getIsPersistent() ) { + DataCenter zone = _dcDao.findById(zoneId); + DeployDestination dest = new DeployDestination(zone, null, null, null); + Account callerAccount = UserContext.current().getCaller(); + UserVO callerUser = _userDao.findById(UserContext.current().getCallerUserId()); + Journal journal = new Journal.LogJournal("Implementing " + guestNetwork, s_logger); + ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), journal, callerUser, callerAccount); + s_logger.debug("Implementing network " + guestNetwork + " as a part of network provision for persistent network"); + try { + Pair implementedNetwork = implementNetwork(guestNetwork.getId(), dest, context); + if (implementedNetwork.first() == null) { + s_logger.warn("Failed to implement the network " + guestNetwork); + } + guestNetwork = implementedNetwork.second(); + } catch (Exception ex) { + s_logger.warn("Failed to implement network " + guestNetwork + " elements and resources as a part of" + + " network provision due to ", ex); + CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id)" + + " elements and resources as a part of network provision for persistent network"); + e.addProxyObject(guestNetwork, guestNetwork.getId(), "networkId"); + throw e; + } + } return true; } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 622b4481a18..5c70caa5061 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -70,7 +70,9 @@ import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.user.*; import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.UserDao; import com.cloud.utils.AnnotationHelper; +import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.component.Adapters; @@ -117,7 +119,8 @@ public class NetworkServiceImpl implements NetworkService, Manager { AccountDao _accountDao = null; @Inject DomainDao _domainDao = null; - + @Inject + UserDao _userDao = null; @Inject EventDao _eventDao = null; @Inject @@ -887,11 +890,33 @@ public class NetworkServiceImpl implements NetworkService, Manager { txn.commit(); + // if the network offering has persistent set to true, implement the network + if ( ntwkOff.getIsPersistent() ) { + try { + if ( network.getState() == Network.State.Setup ) { + s_logger.debug("Network id=" + network.getId() + " is already provisioned"); + return network; + } + DeployDestination dest = new DeployDestination(zone, null, null, null); + UserVO callerUser = _userDao.findById(UserContext.current().getCallerUserId()); + Journal journal = new Journal.LogJournal("Implementing " + network, s_logger); + ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), journal, callerUser, caller); + s_logger.debug("Implementing network " + network + " as a part of network provision for persistent network"); + Pair implementedNetwork = _networkMgr.implementNetwork(network.getId(), dest, context); + if (implementedNetwork.first() == null) { + s_logger.warn("Failed to provision the network " + network); + } + network = implementedNetwork.second(); + } catch (ResourceUnavailableException ex) { + s_logger.warn("Failed to implement persistent guest network " + network + "due to ", ex); + CloudRuntimeException e = new CloudRuntimeException("Failed to implement persistent guest network"); + e.addProxyObject(network, network.getId(), "networkId"); + throw e; + } + } return network; } - - @Override public List searchForNetworks(ListNetworksCmd cmd) { Long id = cmd.getId(); @@ -1507,9 +1532,9 @@ public class NetworkServiceImpl implements NetworkService, Manager { boolean networkOfferingChanged = false; long oldNetworkOfferingId = network.getNetworkOfferingId(); + NetworkOffering oldNtwkOff = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId); + NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); if (networkOfferingId != null) { - - NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); if (networkOffering == null || networkOffering.isSystemOnly()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find network offering with specified id"); ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId"); @@ -1533,7 +1558,6 @@ public class NetworkServiceImpl implements NetworkService, Manager { } if (networkOfferingId != oldNetworkOfferingId) { - NetworkOffering oldNtwkOff = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId); Collection newProviders = _networkMgr.finalizeServicesAndProvidersForNetwork(networkOffering, network.getPhysicalNetworkId()).values(); Collection oldProviders = _networkMgr.finalizeServicesAndProvidersForNetwork(oldNtwkOff, network.getPhysicalNetworkId()).values(); @@ -1680,6 +1704,24 @@ public class NetworkServiceImpl implements NetworkService, Manager { } } + // 4) if network has been upgraded from a non persistent ntwk offering to a persistent ntwk offering, + // implement the network if its not already + if ( !oldNtwkOff.getIsPersistent() && networkOffering.getIsPersistent()) { + if( network.getState() == Network.State.Allocated) { + try { + DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null); + _networkMgr.implementNetwork(network.getId(), dest, context); + } catch (Exception ex) { + s_logger.warn("Failed to implement network " + network + " elements and resources as a part o" + + "f network update due to ", ex); + CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified" + + " id) elements and resources as a part of network update"); + e.addProxyObject(network, networkId, "networkId"); + throw e; + } + } + } + return getNetwork(network.getId()); } diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java index 2c5b46da577..f21854e851c 100644 --- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -74,6 +74,7 @@ public class NetworkDaoImpl extends GenericDaoBase implements N final GenericSearchBuilder CountByZoneAndURI; final GenericSearchBuilder VpcNetworksCount; final SearchBuilder OfferingAccountNetworkSearch; + final GenericSearchBuilder GarbageCollectedSearch; ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class); NetworkAccountDaoImpl _accountsDao = ComponentLocator.inject(NetworkAccountDaoImpl.class); @@ -81,6 +82,7 @@ public class NetworkDaoImpl extends GenericDaoBase implements N NetworkOpDaoImpl _opDao = ComponentLocator.inject(NetworkOpDaoImpl.class); NetworkServiceMapDaoImpl _ntwkSvcMap = ComponentLocator.inject(NetworkServiceMapDaoImpl.class); NetworkOfferingDaoImpl _ntwkOffDao = ComponentLocator.inject(NetworkOfferingDaoImpl.class); + NetworkOpDaoImpl _ntwkOpDao = ComponentLocator.inject(NetworkOpDaoImpl.class); final TableGenerator _tgMacAddress; @@ -215,6 +217,19 @@ public class NetworkDaoImpl extends GenericDaoBase implements N OfferingAccountNetworkSearch.and("zoneId", OfferingAccountNetworkSearch.entity().getDataCenterId(), Op.EQ); OfferingAccountNetworkSearch.and("type", OfferingAccountNetworkSearch.entity().getGuestType(), Op.EQ); OfferingAccountNetworkSearch.done(); + + GarbageCollectedSearch = createSearchBuilder(Long.class); + GarbageCollectedSearch.selectField(GarbageCollectedSearch.entity().getId()); + SearchBuilder join7 = _ntwkOpDao.createSearchBuilder(); + join7.and("activenics", join7.entity().getActiveNicsCount(), Op.EQ); + join7.and("gc", join7.entity().isGarbageCollected(), Op.EQ); + join7.and("check", join7.entity().isCheckForGc(), Op.EQ); + GarbageCollectedSearch.join("ntwkOpGC", join7, GarbageCollectedSearch.entity().getId(), join7.entity().getId(), JoinBuilder.JoinType.INNER); + SearchBuilder join8 = _ntwkOffDao.createSearchBuilder(); + join8.and("isPersistent", join8.entity().getIsPersistent(), Op.EQ); + GarbageCollectedSearch.join("ntwkOffGC", join8, GarbageCollectedSearch.entity().getNetworkOfferingId(), join8.entity().getId(), JoinBuilder.JoinType.INNER); + GarbageCollectedSearch.done(); + } @Override @@ -398,7 +413,12 @@ public class NetworkDaoImpl extends GenericDaoBase implements N @Override public List findNetworksToGarbageCollect() { - return _opDao.getNetworksToGarbageCollect(); + SearchCriteria sc = GarbageCollectedSearch.create(); + sc.setJoinParameters("ntwkOffGC", "isPersistent", false); + sc.setJoinParameters("ntwkOpGC", "activenics", 0); + sc.setJoinParameters("ntwkOpGC", "gc", true); + sc.setJoinParameters("ntwkOpGC", "check", true); + return customSearch(sc, null); } @Override diff --git a/server/src/com/cloud/network/dao/NetworkOpDaoImpl.java b/server/src/com/cloud/network/dao/NetworkOpDaoImpl.java index 298156e067c..bc46481ead1 100644 --- a/server/src/com/cloud/network/dao/NetworkOpDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkOpDaoImpl.java @@ -16,8 +16,6 @@ // under the License. package com.cloud.network.dao; -import java.util.List; - import com.cloud.utils.db.Attribute; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDaoBase; @@ -31,7 +29,6 @@ import com.cloud.utils.db.UpdateBuilder; public class NetworkOpDaoImpl extends GenericDaoBase implements GenericDao { protected final SearchBuilder AllFieldsSearch; protected final GenericSearchBuilder ActiveNicsSearch; - protected final GenericSearchBuilder GarbageCollectSearch; protected final Attribute _activeNicsAttribute; protected NetworkOpDaoImpl() { @@ -45,27 +42,11 @@ public class NetworkOpDaoImpl extends GenericDaoBase implemen AllFieldsSearch = createSearchBuilder(); AllFieldsSearch.and("network", AllFieldsSearch.entity().getId(), Op.EQ); AllFieldsSearch.done(); - - GarbageCollectSearch = createSearchBuilder(Long.class); - GarbageCollectSearch.selectField(GarbageCollectSearch.entity().getId()); - GarbageCollectSearch.and("activenics", GarbageCollectSearch.entity().getActiveNicsCount(), Op.EQ); - GarbageCollectSearch.and("gc", GarbageCollectSearch.entity().isGarbageCollected(), Op.EQ); - GarbageCollectSearch.and("check", GarbageCollectSearch.entity().isCheckForGc(), Op.EQ); - GarbageCollectSearch.done(); - + _activeNicsAttribute = _allAttributes.get("activeNicsCount"); assert _activeNicsAttribute != null : "Cannot find activeNicsCount"; } - - public List getNetworksToGarbageCollect() { - SearchCriteria sc = GarbageCollectSearch.create(); - sc.setParameters("activenics", 0); - sc.setParameters("gc", true); - sc.setParameters("check", true); - - return customSearch(sc, null); - } - + public int getActiveNics(long networkId) { SearchCriteria sc = ActiveNicsSearch.create(); sc.setParameters("network", networkId); diff --git a/server/src/com/cloud/offerings/NetworkOfferingVO.java b/server/src/com/cloud/offerings/NetworkOfferingVO.java index efaca764020..5de76a526b5 100755 --- a/server/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/server/src/com/cloud/offerings/NetworkOfferingVO.java @@ -116,6 +116,9 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "inline") boolean inline; + @Column(name = "is_persistent") + boolean isPersistent; + @Override public String getDisplayText() { return displayText; @@ -256,7 +259,7 @@ public class NetworkOfferingVO implements NetworkOffering { } public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault, - Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean specifyIpRanges) { + Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean specifyIpRanges, boolean isPersistent) { this.name = name; this.displayText = displayText; this.rateMbps = rateMbps; @@ -278,12 +281,13 @@ public class NetworkOfferingVO implements NetworkOffering { this.elasticLb = false; this.inline = false; this.specifyIpRanges = specifyIpRanges; + this.isPersistent=isPersistent; } public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, - boolean specifyIpRanges, boolean inline) { - this(name, displayText, trafficType, systemOnly, specifyVlan, rateMbps, multicastRateMbps, isDefault, availability, tags, guestType, conserveMode, specifyIpRanges); + boolean specifyIpRanges, boolean inline, boolean isPersistent) { + this(name, displayText, trafficType, systemOnly, specifyVlan, rateMbps, multicastRateMbps, isDefault, availability, tags, guestType, conserveMode, specifyIpRanges, isPersistent); this.dedicatedLB = dedicatedLb; this.sharedSourceNat = sharedSourceNat; this.redundantRouter = redundantRouter; @@ -304,13 +308,13 @@ public class NetworkOfferingVO implements NetworkOffering { * TODO */ public NetworkOfferingVO(String name, TrafficType trafficType, boolean specifyIpRanges) { - this(name, "System Offering for " + name, trafficType, true, false, 0, 0, true, Availability.Required, null, null, true, specifyIpRanges); + this(name, "System Offering for " + name, trafficType, true, false, 0, 0, true, Availability.Required, null, null, true, specifyIpRanges, false); this.state = State.Enabled; } public NetworkOfferingVO(String name, Network.GuestType guestType) { this(name, "System Offering for " + name, TrafficType.Guest, true, true, 0, 0, true, Availability.Optional, - null, Network.GuestType.Isolated, true, false); + null, Network.GuestType.Isolated, true, false, false); this.state = State.Enabled; } @@ -365,4 +369,13 @@ public class NetworkOfferingVO implements NetworkOffering { public boolean isInline() { return inline; } + + public void setIsPersistent(Boolean isPersistent) { + this.isPersistent = isPersistent; + } + + public boolean getIsPersistent() { + return isPersistent; + } + } diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 98a67376b45..ebf140f2318 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -911,7 +911,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Shared Security group enabled networks", TrafficType.Guest, false, true, null, null, true, Availability.Optional, - null, Network.GuestType.Shared, true, true); + null, Network.GuestType.Shared, true, true, false); defaultSharedSGNetworkOffering.setState(NetworkOffering.State.Enabled); defaultSharedSGNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultSharedSGNetworkOffering); @@ -928,7 +928,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Shared networks", TrafficType.Guest, false, true, null, null, true, Availability.Optional, - null, Network.GuestType.Shared, true, true); + null, Network.GuestType.Shared, true, true, false); defaultSharedNetworkOffering.setState(NetworkOffering.State.Enabled); defaultSharedNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultSharedNetworkOffering); @@ -945,7 +945,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest, false, false, null, null, true, Availability.Required, - null, Network.GuestType.Isolated, true, false); + null, Network.GuestType.Isolated, true, false, false); defaultIsolatedSourceNatEnabledNetworkOffering.setState(NetworkOffering.State.Enabled); defaultIsolatedSourceNatEnabledNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultIsolatedSourceNatEnabledNetworkOffering); @@ -963,7 +963,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Isolated networks with no Source Nat service", TrafficType.Guest, false, true, null, null, true, Availability.Optional, - null, Network.GuestType.Isolated, true, true); + null, Network.GuestType.Isolated, true, true, false); defaultIsolatedEnabledNetworkOffering.setState(NetworkOffering.State.Enabled); defaultIsolatedEnabledNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultIsolatedEnabledNetworkOffering); @@ -980,7 +980,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, Availability.Optional, - null, Network.GuestType.Shared, true, false, false, false, true, true, true, false); + null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false); defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled); defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering); @@ -997,7 +997,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Isolated Vpc networks with Source Nat service enabled", TrafficType.Guest, false, false, null, null, true, Availability.Optional, - null, Network.GuestType.Isolated, false, false); + null, Network.GuestType.Isolated, false, false, false); defaultNetworkOfferingForVpcNetworks.setState(NetworkOffering.State.Enabled); defaultNetworkOfferingForVpcNetworks = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetworkOfferingForVpcNetworks); @@ -1027,7 +1027,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Isolated Vpc networks with Source Nat service enabled and LB service Disabled", TrafficType.Guest, false, false, null, null, true, Availability.Optional, - null, Network.GuestType.Isolated, false, false); + null, Network.GuestType.Isolated, false, false, false); defaultNetworkOfferingForVpcNetworksNoLB.setState(NetworkOffering.State.Enabled); defaultNetworkOfferingForVpcNetworksNoLB = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetworkOfferingForVpcNetworksNoLB); diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index a53e1328c2e..afa6545a21e 100644 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -70,6 +70,7 @@ import com.cloud.network.Network.Service; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.*; import com.cloud.network.element.UserDataServiceProvider; +import com.cloud.network.guru.NetworkGuru; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.rules.FirewallManager; import com.cloud.network.rules.FirewallRuleVO; @@ -112,6 +113,7 @@ import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.SSHKeyPairDao; import com.cloud.user.dao.UserDao; import com.cloud.uservm.UserVm; +import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.PasswordGenerator; @@ -3917,6 +3919,30 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), newAccount.getAccountName() + "-network", newAccount.getAccountName() + "-network", null, null, null, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null); + // if the network offering has persistent set to true, implement the network + if (requiredOfferings.get(0).getIsPersistent()) { + DeployDestination dest = new DeployDestination(zone, null, null, null); + UserVO callerUser = _userDao.findById(UserContext.current().getCallerUserId()); + Journal journal = new Journal.LogJournal("Implementing " + newNetwork, s_logger); + ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), + journal, callerUser, caller); + s_logger.debug("Implementing the network for account" + newNetwork + " as a part of" + + " network provision for persistent networks"); + try { + Pair implementedNetwork = _networkMgr.implementNetwork(newNetwork.getId(), dest, context); + if (implementedNetwork.first() == null) { + s_logger.warn("Failed to implement the network " + newNetwork); + } + newNetwork = implementedNetwork.second(); + } catch (Exception ex) { + s_logger.warn("Failed to implement network " + newNetwork + " elements and" + + " resources as a part of network provision for persistent network due to ", ex); + CloudRuntimeException e = new CloudRuntimeException("Failed to implement network" + + " (with specified id) elements and resources as a part of network provision"); + e.addProxyObject(newNetwork, newNetwork.getId(), "networkId"); + throw e; + } + } defaultNetwork = _networkDao.findById(newNetwork.getId()); } else if (virtualNetworks.size() > 1) { throw new InvalidParameterValueException("More than 1 default Isolated networks are found " + diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java index 17ad2e1ddb4..6fb057e8f7c 100644 --- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -482,7 +482,7 @@ public class MockConfigurationManagerImpl implements ConfigurationManager, Confi @Override public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability, Integer networkRate, Map> serviceProviderMap, boolean isDefault, GuestType type, boolean systemOnly, Long serviceOfferingId, boolean conserveMode, - Map> serviceCapabilityMap, boolean specifyIpRanges) { + Map> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent) { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 5d9c4367310..382068a47c2 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -215,8 +215,6 @@ public class MockNetworkManagerImpl implements NetworkManager, NetworkService, M - - /* (non-Javadoc) * @see com.cloud.network.NetworkService#searchForNetworks(com.cloud.api.commands.ListNetworksCmd) */ diff --git a/server/test/com/cloud/vpc/dao/MockNetworkOfferingDaoImpl.java b/server/test/com/cloud/vpc/dao/MockNetworkOfferingDaoImpl.java index 496864be198..865daa4b9a0 100644 --- a/server/test/com/cloud/vpc/dao/MockNetworkOfferingDaoImpl.java +++ b/server/test/com/cloud/vpc/dao/MockNetworkOfferingDaoImpl.java @@ -100,28 +100,28 @@ public class MockNetworkOfferingDaoImpl extends GenericDaoBase