diff --git a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java index c64b9320245..3aab57d5d3d 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java @@ -29,7 +29,8 @@ public interface VpcOffering extends InternalIdentity, Identity { public static final String defaultVPCOfferingName = "Default VPC offering"; public static final String defaultVPCNSOfferingName = "Default VPC offering with Netscaler"; public static final String redundantVPCOfferingName = "Redundant VPC offering"; - public static final String DEFAULT_VPC_NSX_OFFERING_NAME = "VPC offering with NSX"; + public static final String DEFAULT_VPC_NAT_NSX_OFFERING_NAME = "VPC offering with NSX - NAT Mode"; + public static final String DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME = "VPC offering with NSX - Route Mode"; /** * @@ -54,6 +55,10 @@ public interface VpcOffering extends InternalIdentity, Identity { */ boolean isDefault(); + boolean isForNsx(); + + String getNsxMode(); + /** * @return service offering id used by VPC virtual router */ diff --git a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java index 5cccd6c5a82..1ce3cf8ab0e 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java @@ -36,7 +36,8 @@ public interface VpcProvisioningService { VpcOffering createVpcOffering(String name, String displayText, List supportedServices, Map> serviceProviders, Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol, - Long serviceOfferingId, List domainIds, List zoneIds, VpcOffering.State state); + Long serviceOfferingId, Boolean forNsx, String mode, + List domainIds, List zoneIds, VpcOffering.State state); Pair,Integer> listVpcOfferings(ListVPCOfferingsCmd cmd); diff --git a/api/src/main/java/com/cloud/offering/NetworkOffering.java b/api/src/main/java/com/cloud/offering/NetworkOffering.java index afe2a255f5b..6a68ab1246a 100644 --- a/api/src/main/java/com/cloud/offering/NetworkOffering.java +++ b/api/src/main/java/com/cloud/offering/NetworkOffering.java @@ -43,6 +43,11 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol } + public enum NsxMode { + NATTED, + ROUTED + } + public final static String SystemPublicNetwork = "System-Public-Network"; public final static String SystemControlNetwork = "System-Control-Network"; public final static String SystemManagementNetwork = "System-Management-Network"; @@ -52,7 +57,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService"; public static final String DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE = "DefaultTungstenSharedNetworkOfferingWithSGService"; - public static final String DEFAULT_NSX_OFFERING = "DefaultNSXNetworkOffering"; + public static final String DEFAULT_NAT_NSX_OFFERING = "DefaultNATNSXNetworkOffering"; + public static final String DEFAULT_ROUTER_NSX_OFFERING = "DefaultRouteNSXNetworkOffering"; public final static String QuickCloudNoServices = "QuickCloudNoServices"; public final static String DefaultIsolatedNetworkOfferingWithSourceNatService = "DefaultIsolatedNetworkOfferingWithSourceNatService"; public final static String OvsIsolatedNetworkOfferingWithSourceNatService = "OvsIsolatedNetworkOfferingWithSourceNatService"; @@ -93,6 +99,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, boolean isForNsx(); + String getNsxMode(); + TrafficType getTrafficType(); boolean isSpecifyVlan(); diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 3329f42bfc9..7448f8c6e41 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -292,6 +292,7 @@ public class ApiConstants { public static final String MIGRATION_TYPE = "migrationtype"; public static final String MEMORY = "memory"; public static final String MODE = "mode"; + public static final String NSX_MODE = "nsxmode"; public static final String NAME = "name"; public static final String METHOD_NAME = "methodname"; public static final String NETWORK_DOMAIN = "networkdomain"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java index 8bf6fce881c..e12ab53c073 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java @@ -24,7 +24,10 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import com.cloud.network.Network; +import com.cloud.network.VirtualRouterProvider; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.collections.CollectionUtils; @@ -47,6 +50,15 @@ import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Availability; import com.cloud.user.Account; +import static com.cloud.network.Network.Service.Dhcp; +import static com.cloud.network.Network.Service.Dns; +import static com.cloud.network.Network.Service.Lb; +import static com.cloud.network.Network.Service.StaticNat; +import static com.cloud.network.Network.Service.SourceNat; +import static com.cloud.network.Network.Service.PortForwarding; +import static com.cloud.network.Network.Service.NetworkACL; +import static com.cloud.network.Network.Service.UserData; + @APICommand(name = "createNetworkOffering", description = "Creates a network offering.", responseObject = NetworkOfferingResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkOfferingCmd extends BaseCmd { @@ -127,6 +139,18 @@ public class CreateNetworkOfferingCmd extends BaseCmd { description = "true if network offering is meant to be used for VPC, false otherwise.") private Boolean forVpc; + @Parameter(name = ApiConstants.FOR_NSX, + type = CommandType.BOOLEAN, + description = "true if network offering is meant to be used for NSX, false otherwise.", + since = "4.20.0") + private Boolean forNsx; + + @Parameter(name = ApiConstants.NSX_MODE, + type = CommandType.STRING, + description = "Indicates the mode with which the network will operate. Valid option: NATTED or ROUTED", + since = "4.20.0") + private String nsxMode; + @Parameter(name = ApiConstants.FOR_TUNGSTEN, type = CommandType.BOOLEAN, description = "true if network offering is meant to be used for Tungsten-Fabric, false otherwise.") @@ -211,7 +235,24 @@ public class CreateNetworkOfferingCmd extends BaseCmd { } public List getSupportedServices() { - return supportedServices == null ? new ArrayList() : supportedServices; + if (!forNsx) { + return supportedServices == null ? new ArrayList() : supportedServices; + } else { + List services = new ArrayList<>(List.of( + Dhcp.getName(), + Dns.getName(), + StaticNat.getName(), + SourceNat.getName(), + PortForwarding.getName(), + UserData.getName(), + Lb.getName() + )); + if (Boolean.TRUE.equals(forVpc)) { + services.add(NetworkACL.getName()); + return services; + } + return services; + } } public String getGuestIpType() { @@ -241,6 +282,14 @@ public class CreateNetworkOfferingCmd extends BaseCmd { return forVpc; } + public Boolean isForNsx() { + return forNsx; + } + + public String getNsxMode() { + return nsxMode; + } + public Boolean getForTungsten() { return forTungsten; } @@ -261,9 +310,8 @@ public class CreateNetworkOfferingCmd extends BaseCmd { } public Map> getServiceProviders() { - Map> serviceProviderMap = null; - if (serviceProviderList != null && !serviceProviderList.isEmpty()) { - serviceProviderMap = new HashMap>(); + Map> serviceProviderMap = new HashMap>(); + if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isForNsx()) { Collection servicesCollection = serviceProviderList.values(); Iterator iter = servicesCollection.iterator(); while (iter.hasNext()) { @@ -279,11 +327,29 @@ public class CreateNetworkOfferingCmd extends BaseCmd { providerList.add(provider); serviceProviderMap.put(service, providerList); } + } else if (Boolean.TRUE.equals(forNsx)) { + getServiceProviderMapForNsx(serviceProviderMap); } - return serviceProviderMap; } + private void getServiceProviderMapForNsx(Map> serviceProviderMap) { + String routerProvider = Boolean.TRUE.equals(getForVpc()) ? VirtualRouterProvider.Type.VPCVirtualRouter.name() : + VirtualRouterProvider.Type.VirtualRouter.name(); + List unsupportedServices = List.of("Vpn", "SecurityGroup", "Connectivity", + "Gateway", "Firewall", "BaremetalPxeService"); + List routerSupported = List.of("Dhcp", "Dns", "UserData"); + List allServices = Service.listAllServices().stream().map(Service::getName).collect(Collectors.toList()); + for (String service : allServices) { + if (unsupportedServices.contains(service)) + continue; + if (routerSupported.contains(service)) + serviceProviderMap.put(service, List.of(routerProvider)); + else + serviceProviderMap.put(service, List.of(Network.Provider.Nsx.getName())); + } + } + public Map getServiceCapabilities(Service service) { Map capabilityMap = null; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java index b69e7f4a828..c55a4571733 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java @@ -23,8 +23,13 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.Network; +import com.cloud.network.VirtualRouterProvider; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.collections.CollectionUtils; @@ -45,6 +50,15 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.network.vpc.VpcOffering; import com.cloud.user.Account; +import static com.cloud.network.Network.Service.Dhcp; +import static com.cloud.network.Network.Service.Dns; +import static com.cloud.network.Network.Service.Lb; +import static com.cloud.network.Network.Service.StaticNat; +import static com.cloud.network.Network.Service.SourceNat; +import static com.cloud.network.Network.Service.PortForwarding; +import static com.cloud.network.Network.Service.NetworkACL; +import static com.cloud.network.Network.Service.UserData; + @APICommand(name = "createVPCOffering", description = "Creates VPC offering", responseObject = VpcOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { @@ -62,7 +76,6 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { @Parameter(name = ApiConstants.SUPPORTED_SERVICES, type = CommandType.LIST, - required = true, collectionType = CommandType.STRING, description = "services supported by the vpc offering") private List supportedServices; @@ -101,6 +114,18 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { since = "4.13") private List zoneIds; + @Parameter(name = ApiConstants.FOR_NSX, + type = CommandType.BOOLEAN, + description = "true if network offering is meant to be used for NSX, false otherwise.", + since = "4.20.0") + private Boolean forNsx; + + @Parameter(name = ApiConstants.NSX_MODE, + type = CommandType.STRING, + description = "Indicates the mode with which the network will operate. Valid option: NATTED or ROUTED", + since = "4.20.0") + private String nsxMode; + @Parameter(name = ApiConstants.ENABLE, type = CommandType.BOOLEAN, description = "set to true if the offering is to be enabled during creation. Default is false", @@ -120,13 +145,35 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { } public List getSupportedServices() { + if (!forNsx && CollectionUtils.isEmpty(supportedServices)) { + throw new InvalidParameterValueException("Supported services needs to be provided"); + } + if (forNsx) { + return List.of( + Dhcp.getName(), + Dns.getName(), + Lb.getName(), + StaticNat.getName(), + SourceNat.getName(), + NetworkACL.getName(), + PortForwarding.getName(), + UserData.getName() + ); + } return supportedServices; } + public Boolean isForNsx() { + return !Objects.isNull(forNsx) && forNsx; + } + + public String getNsxMode() { + return nsxMode; + } + public Map> getServiceProviders() { - Map> serviceProviderMap = null; - if (serviceProviderList != null && !serviceProviderList.isEmpty()) { - serviceProviderMap = new HashMap>(); + Map> serviceProviderMap = new HashMap>();; + if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isForNsx()) { Collection> servicesCollection = serviceProviderList.values(); Iterator> iter = servicesCollection.iterator(); while (iter.hasNext()) { @@ -134,7 +181,7 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { if (s_logger.isTraceEnabled()) { s_logger.trace("service provider entry specified: " + obj); } - HashMap services = (HashMap)obj; + HashMap services = (HashMap) obj; String service = services.get("service"); String provider = services.get("provider"); List providerList = null; @@ -146,11 +193,28 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { providerList.add(provider); serviceProviderMap.put(service, providerList); } + } else if (Boolean.TRUE.equals(forNsx)) { + getServiceProviderMapForNsx(serviceProviderMap); } return serviceProviderMap; } + private void getServiceProviderMapForNsx(Map> serviceProviderMap) { + List unsupportedServices = List.of("Vpn", "BaremetalPxeService", "SecurityGroup", "Connectivity", + "Gateway", "Firewall"); + List routerSupported = List.of("Dhcp", "Dns", "UserData"); + List allServices = Network.Service.listAllServices().stream().map(Network.Service::getName).collect(Collectors.toList()); + for (String service : allServices) { + if (unsupportedServices.contains(service)) + continue; + if (routerSupported.contains(service)) + serviceProviderMap.put(service, List.of(VirtualRouterProvider.Type.VPCVirtualRouter.name())); + else + serviceProviderMap.put(service, List.of(Network.Provider.Nsx.getName())); + } + } + public Map> getServiceCapabilityList() { return serviceCapabilityList; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java index 4685580e4b5..2594488c5be 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java @@ -107,6 +107,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations { @Param(description = "true if network offering can be used by Tungsten-Fabric networks only") private Boolean forTungsten; + @SerializedName(ApiConstants.NSX_MODE) + @Param(description = "Mode in which the network will operate. This parameter is only relevant for NSX offerings") + private String nsxMode; + @SerializedName(ApiConstants.IS_PERSISTENT) @Param(description = "true if network offering supports persistent networks, false otherwise") private Boolean isPersistent; @@ -227,6 +231,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations { this.forTungsten = forTungsten; } + public void setNsxMode(String nsxMode) { + this.nsxMode = nsxMode; + } + public void setIsPersistent(Boolean isPersistent) { this.isPersistent = isPersistent; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java index 6881969646b..ce00827f06d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java @@ -63,9 +63,17 @@ public class VpcOfferingResponse extends BaseResponse { private Boolean supportsDistributedRouter; @SerializedName((ApiConstants.SUPPORTS_REGION_LEVEL_VPC)) - @Param(description = " indicated if the offering can support region level vpc", since = "4.4") + @Param(description = "indicated if the offering can support region level vpc", since = "4.4") private Boolean supportsRegionLevelVpc; + @SerializedName(ApiConstants.FOR_NSX) + @Param(description = "true if vpc offering can be used by NSX networks only") + private Boolean forNsx; + + @SerializedName(ApiConstants.NSX_MODE) + @Param(description = "Mode in which the network will operate. This parameter is only relevant for NSX offerings") + private String nsxMode; + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description = "the domain ID(s) this disk offering belongs to. Ignore this information as it is not currently applicable.") private String domainId; @@ -138,6 +146,14 @@ public class VpcOfferingResponse extends BaseResponse { this.domain = domain; } + public void setForNsx(Boolean forNsx) { + this.forNsx = forNsx; + } + + public void setNsxMode(String nsxMode) { + this.nsxMode = nsxMode; + } + public String getZoneId() { return zoneId; } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java index 16b716d7d63..290a2850c9a 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java @@ -52,15 +52,15 @@ public class CreateVPCOfferingCmdTest { IllegalAccessException { CreateVPCOfferingCmd cmd = new CreateVPCOfferingCmd(); ApiCmdTestUtil.set(cmd, ApiConstants.SERVICE_PROVIDER_LIST, new HashMap>()); - Assert.assertNull(cmd.getServiceProviders()); + Assert.assertTrue(cmd.getServiceProviders().isEmpty()); } @Test - public void getDetailsNull() throws IllegalArgumentException, + public void getDetailsEmpty() throws IllegalArgumentException, IllegalAccessException { CreateVPCOfferingCmd cmd = new CreateVPCOfferingCmd(); ApiCmdTestUtil.set(cmd, ApiConstants.SERVICE_PROVIDER_LIST, null); - Assert.assertNull(cmd.getServiceProviders()); + Assert.assertTrue(cmd.getServiceProviders().isEmpty()); } @Test diff --git a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java index 1146a33861d..b0fbd30691a 100644 --- a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java +++ b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java @@ -225,7 +225,7 @@ public interface ConfigurationManager { Integer networkRate, Map> serviceProviderMap, boolean isDefault, Network.GuestType type, boolean systemOnly, Long serviceOfferingId, boolean conserveMode, Map> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent, Map details, boolean egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive, Boolean forVpc, - Boolean forTungsten, Boolean forNsx, List domainIds, List zoneIds, boolean enableOffering, final NetUtils.InternetProtocol internetProtocol); + Boolean forTungsten, Boolean forNsx, String mode, List domainIds, List zoneIds, boolean enableOffering, final NetUtils.InternetProtocol internetProtocol); Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, boolean forSystemVms, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 70176ebb29f..efecfc3d3f2 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -540,27 +540,27 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra if (_networkOfferingDao.findByUniqueName(NetworkOffering.QuickCloudNoServices) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.QuickCloudNoServices, "Offering for QuickCloud with no services", TrafficType.Guest, null, true, Availability.Optional, null, new HashMap>(), true, Network.GuestType.Shared, false, null, true, null, true, - false, null, false, null, true, false, false, false, null, null, true, null); + false, null, false, null, true, false, false, false, null, null, null, true, null); } //#2 - SG enabled network offering 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, false, null, false, null, true, false, false, false, null, null, true, null); + null, true, false, null, false, null, true, false, false, false, null, null, null, true, null); } //#3 - shared network offering with no SG service 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, false, null, false, - null, true, false, false, false, null, null, true, null); + null, true, false, false, false, null,null, null, true, null); } if (_networkOfferingDao.findByUniqueName(NetworkOffering.DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE, "Offering for Tungsten Shared Security group enabled networks", TrafficType.Guest, null, true, Availability.Optional, null, defaultTungstenSharedSGEnabledNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, - null, true, false, null, false, null, true, false, true, false, null, null, true, null); + null, true, false, null, false, null, true, false, true, false, null, null,null, true, null); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } @@ -570,14 +570,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService, "Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest, null, false, Availability.Required, null, defaultIsolatedSourceNatEnabledNetworkOfferingProviders, true, Network.GuestType.Isolated, false, null, true, null, false, false, null, false, null, - true, false, false, false, null, null, true, null); + true, false, false, false, null, null,null, true, null); } //#5 - default vpc offering with LB service if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks) == null) { 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, false, null, false, null, true, true, false, false, null, null, true, null); + defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null,true, null); } //#6 - default vpc offering with no LB service @@ -586,14 +586,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra defaultVPCOffProviders.remove(Service.Lb); 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, false, null, false, null, true, true, false, false, null, null, true, null); + null, defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null,true, null); } //#7 - isolated offering with source nat disabled if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOffering) == null) { 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, false, null, true, false, false, false, null, null, true, null); + true, null, true, false, null, false, null, true, false, false, false, null, null, null, true, null); } //#8 - network offering with internal lb service @@ -615,7 +615,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB, "Offering for Isolated VPC networks with Internal Lb support", TrafficType.Guest, null, false, Availability.Optional, null, internalLbOffProviders, - true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, true, null); + true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null, true, null); offering.setInternalLb(true); offering.setPublicLb(false); _networkOfferingDao.update(offering.getId(), offering); @@ -646,7 +646,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra 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, false, null, false, null, true, false, false, false, null, null, true, null); + netscalerServiceProviders, true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap, true, false, null, false, null, true, false, false, false, null, null, null, true, null); offering.setDedicatedLB(false); _networkOfferingDao.update(offering.getId(), offering); } diff --git a/engine/schema/src/main/java/com/cloud/network/vpc/VpcOfferingVO.java b/engine/schema/src/main/java/com/cloud/network/vpc/VpcOfferingVO.java index aa26f16568a..350dda3f3b8 100644 --- a/engine/schema/src/main/java/com/cloud/network/vpc/VpcOfferingVO.java +++ b/engine/schema/src/main/java/com/cloud/network/vpc/VpcOfferingVO.java @@ -58,6 +58,12 @@ public class VpcOfferingVO implements VpcOffering { @Column(name = "default") boolean isDefault = false; + @Column(name = "for_nsx") + boolean forNsx = false; + + @Column(name = "nsx_mode") + String nsxMode; + @Column(name = GenericDao.REMOVED_COLUMN) Date removed; @@ -144,6 +150,22 @@ public class VpcOfferingVO implements VpcOffering { return isDefault; } + public boolean isForNsx() { + return forNsx; + } + + public void setForNsx(boolean forNsx) { + this.forNsx = forNsx; + } + + public String getNsxMode() { + return nsxMode; + } + + public void setNsxMode(String nsxMode) { + this.nsxMode = nsxMode; + } + public void setUniqueName(String uniqueName) { this.uniqueName = uniqueName; } diff --git a/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java index edc89f3cb9a..b2fabf2e3cd 100644 --- a/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java +++ b/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java @@ -139,6 +139,9 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "for_nsx") boolean forNsx = false; + @Column(name = "nsx_mode") + String nsxMode; + @Column(name = "egress_default_policy") boolean egressdefaultpolicy; @@ -207,6 +210,15 @@ public class NetworkOfferingVO implements NetworkOffering { this.forNsx = forNsx; } + @Override + public String getNsxMode() { + return nsxMode; + } + + public void setNsxMode(String nsxMode) { + this.nsxMode = nsxMode; + } + @Override public long getId() { return id; diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql index a429c37d4d6..0a461570ac5 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql @@ -214,8 +214,11 @@ BEGIN -- NSX Plugin -- CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.network_offerings','for_nsx', 'int(1) unsigned DEFAULT "0" COMMENT "is nsx enabled for the resource"'); +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.network_offerings','nsx_mode', 'varchar(32) COMMENT "mode in which the network would route traffic"'); +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','for_nsx', 'int(1) unsigned DEFAULT "0" COMMENT "is nsx enabled for the resource"'); +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','nsx_mode', 'varchar(32) COMMENT "mode in which the network would route traffic"'); --- Network offering with multi-domains and multi-zones +-- Network offering with NSX related columns DROP VIEW IF EXISTS `cloud`.`network_offering_view`; CREATE VIEW `cloud`.`network_offering_view` AS SELECT @@ -259,6 +262,7 @@ SELECT `network_offerings`.`for_vpc` AS `for_vpc`, `network_offerings`.`for_tungsten` AS `for_tungsten`, `network_offerings`.`for_nsx` AS `for_nsx`, + `network_offerings`.`nsx_mode` AS `nsx_mode`, `network_offerings`.`service_package_id` AS `service_package_id`, GROUP_CONCAT(DISTINCT(domain.id)) AS domain_id, GROUP_CONCAT(DISTINCT(domain.uuid)) AS domain_uuid, @@ -285,3 +289,46 @@ GROUP BY -- Set removed state for all removed accounts UPDATE `cloud`.`account` SET state='removed' WHERE `removed` IS NOT NULL; + +-- VPC offering with NSX related columns +DROP VIEW IF EXISTS `cloud`.`vpc_offering_view`; +CREATE VIEW `cloud`.`vpc_offering_view` AS +SELECT + `vpc_offerings`.`id` AS `id`, + `vpc_offerings`.`uuid` AS `uuid`, + `vpc_offerings`.`name` AS `name`, + `vpc_offerings`.`unique_name` AS `unique_name`, + `vpc_offerings`.`display_text` AS `display_text`, + `vpc_offerings`.`state` AS `state`, + `vpc_offerings`.`default` AS `default`, + `vpc_offerings`.`for_nsx` AS `for_nsx`, + `vpc_offerings`.`nsx_mode` AS `nsx_mode`, + `vpc_offerings`.`created` AS `created`, + `vpc_offerings`.`removed` AS `removed`, + `vpc_offerings`.`service_offering_id` AS `service_offering_id`, + `vpc_offerings`.`supports_distributed_router` AS `supports_distributed_router`, + `vpc_offerings`.`supports_region_level_vpc` AS `supports_region_level_vpc`, + `vpc_offerings`.`redundant_router_service` AS `redundant_router_service`, + `vpc_offerings`.`sort_key` AS `sort_key`, + GROUP_CONCAT(DISTINCT(domain.id)) AS domain_id, + GROUP_CONCAT(DISTINCT(domain.uuid)) AS domain_uuid, + GROUP_CONCAT(DISTINCT(domain.name)) AS domain_name, + GROUP_CONCAT(DISTINCT(domain.path)) AS domain_path, + GROUP_CONCAT(DISTINCT(zone.id)) AS zone_id, + GROUP_CONCAT(DISTINCT(zone.uuid)) AS zone_uuid, + GROUP_CONCAT(DISTINCT(zone.name)) AS zone_name, + `offering_details`.value AS internet_protocol +FROM + `cloud`.`vpc_offerings` + LEFT JOIN + `cloud`.`vpc_offering_details` AS `domain_details` ON `domain_details`.`offering_id` = `vpc_offerings`.`id` AND `domain_details`.`name`='domainid' + LEFT JOIN + `cloud`.`domain` AS `domain` ON FIND_IN_SET(`domain`.`id`, `domain_details`.`value`) + LEFT JOIN + `cloud`.`vpc_offering_details` AS `zone_details` ON `zone_details`.`offering_id` = `vpc_offerings`.`id` AND `zone_details`.`name`='zoneid' + LEFT JOIN + `cloud`.`data_center` AS `zone` ON FIND_IN_SET(`zone`.`id`, `zone_details`.`value`) + LEFT JOIN + `cloud`.`vpc_offering_details` AS `offering_details` ON `offering_details`.`offering_id` = `vpc_offerings`.`id` AND `offering_details`.`name`='internetprotocol' +GROUP BY + `vpc_offerings`.`id`; diff --git a/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailManagerImpl.java b/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailManagerImpl.java index 372e268a2ff..6ce4c91bea6 100644 --- a/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailManagerImpl.java +++ b/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/ContrailManagerImpl.java @@ -219,7 +219,7 @@ public class ContrailManagerImpl extends ManagerBase implements ContrailManager ConfigurationManager configMgr = (ConfigurationManager) _configService; NetworkOfferingVO voffer = configMgr.createNetworkOffering(offeringName, offeringDisplayText, TrafficType.Public, null, true, Availability.Optional, null, serviceProviderMap, true, - Network.GuestType.Shared, false, null, false, null, true, false, null, true, null, false, false, false, false, null, null, true, null); + Network.GuestType.Shared, false, null, false, null, true, false, null, true, null, false, false, false, false, null, null, null, true, null); long id = voffer.getId(); _networkOfferingDao.update(id, voffer); return _networkOfferingDao.findById(id); @@ -254,7 +254,7 @@ public class ContrailManagerImpl extends ManagerBase implements ContrailManager ConfigurationManager configMgr = (ConfigurationManager)_configService; NetworkOfferingVO voffer = configMgr.createNetworkOffering(offeringName, offeringDisplayText, TrafficType.Guest, null, false, Availability.Optional, null, serviceProviderMap, true, - Network.GuestType.Isolated, false, null, false, null, false, true, null, true, null, false, offeringName.equals(vpcRouterOfferingName), false, false, null, null, true, null); + Network.GuestType.Isolated, false, null, false, null, false, true, null, true, null, false, offeringName.equals(vpcRouterOfferingName), false, false, null, null, null, true, null); if (offeringName.equals(vpcRouterOfferingName)) { voffer.setInternalLb(true); } @@ -295,7 +295,7 @@ public class ContrailManagerImpl extends ManagerBase implements ContrailManager } serviceProviderMap.put(svc, providerSet); } - vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null, null, null, null, null, VpcOffering.State.Enabled); + vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null, null, null, false, null, null, null, VpcOffering.State.Enabled); long id = vpcOffer.getId(); _vpcOffDao.update(id, (VpcOfferingVO)vpcOffer); return _vpcOffDao.findById(id); diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java index b01700cfe2c..edbc2eebffe 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java @@ -118,7 +118,9 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS capabilities.put(Network.Service.Dns, dnsCapabilities); capabilities.put(Network.Service.StaticNat, null); - + capabilities.put(Network.Service.Lb, null); + capabilities.put(Network.Service.PortForwarding, null); + capabilities.put(Network.Service.NetworkACL, null); Map sourceNatCapabilities = new HashMap<>(); sourceNatCapabilities.put(Network.Capability.RedundantRouter, "true"); sourceNatCapabilities.put(Network.Capability.SupportedSourceNatTypes, "peraccount"); @@ -226,7 +228,7 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS @Override public boolean verifyServicesCombination(Set services) { - return false; + return true; } @Override diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java index 70102ec8295..6b0c2472b41 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java @@ -50,6 +50,7 @@ import org.apache.cloudstack.NsxAnswer; import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand; import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand; import org.apache.cloudstack.utils.NsxControllerUtils; + import org.apache.cloudstack.utils.NsxHelper; import org.apache.log4j.Logger; diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 6d4972573ae..0a174e51de0 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -2321,6 +2321,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setForVpc(_configMgr.isOfferingForVpc(offering)); response.setForTungsten(offering.isForTungsten()); response.setForNsx(offering.isForNsx()); + response.setNsxMode(offering.getNsxMode()); response.setServices(serviceResponses); //set network offering details Map details = _ntwkModel.getNtwkOffDetails(offering.getId()); diff --git a/server/src/main/java/com/cloud/api/query/dao/VpcOfferingJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/VpcOfferingJoinDaoImpl.java index af0940609ba..bab22178e61 100644 --- a/server/src/main/java/com/cloud/api/query/dao/VpcOfferingJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/VpcOfferingJoinDaoImpl.java @@ -72,6 +72,8 @@ public class VpcOfferingJoinDaoImpl extends GenericDaoBase detailsStr = cmd.getDetails(); final Boolean egressDefaultPolicy = cmd.getEgressDefaultPolicy(); Boolean forVpc = cmd.getForVpc(); + Boolean forNsx = cmd.isForNsx(); Boolean forTungsten = cmd.getForTungsten(); + String nsxMode = cmd.getNsxMode(); Integer maxconn = null; boolean enableKeepAlive = false; String servicePackageuuid = cmd.getServicePackageId(); @@ -5960,6 +5963,26 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } + if (Boolean.TRUE.equals(forNsx) && Boolean.TRUE.equals(forTungsten)) { + throw new InvalidParameterValueException("Network Offering cannot be for both Tungsten-Fabric and NSX"); + } + + if (Boolean.TRUE.equals(forNsx)) { + if (Objects.isNull(nsxMode)) { + throw new InvalidParameterValueException("Mode for an NSX offering needs to be specified. Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values())); + } + if (!EnumUtils.isValidEnum(NetworkOffering.NsxMode.class, nsxMode)) { + throw new InvalidParameterValueException("Invalid mode passed. Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values())); + } + } else { + if (Objects.nonNull(nsxMode)) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("nsxMode has is ignored for non-NSX enabled zones"); + } + nsxMode = null; + } + } + // Verify traffic type for (final TrafficType tType : TrafficType.values()) { if (tType.name().equalsIgnoreCase(trafficTypeString)) { @@ -6224,7 +6247,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } final NetworkOfferingVO offering = createNetworkOffering(name, displayText, trafficType, tags, specifyVlan, availability, networkRate, serviceProviderMap, false, guestType, false, - serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges, isPersistent, details, egressDefaultPolicy, maxconn, enableKeepAlive, forVpc, forTungsten, false, domainIds, zoneIds, enable, internetProtocol); + serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges, isPersistent, details, egressDefaultPolicy, maxconn, enableKeepAlive, forVpc, forTungsten, forNsx, nsxMode, domainIds, zoneIds, enable, internetProtocol); CallContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name); CallContext.current().putContextParameter(NetworkOffering.class, offering.getId()); return offering; @@ -6369,7 +6392,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati final Long serviceOfferingId, final boolean conserveMode, final Map> serviceCapabilityMap, final boolean specifyIpRanges, final boolean isPersistent, final Map details, final boolean egressDefaultPolicy, final Integer maxconn, final boolean enableKeepAlive, Boolean forVpc, - Boolean forTungsten, Boolean forNsx, final List domainIds, final List zoneIds, final boolean enableOffering, final NetUtils.InternetProtocol internetProtocol) { + Boolean forTungsten, Boolean forNsx, String mode, final List domainIds, final List zoneIds, final boolean enableOffering, final NetUtils.InternetProtocol internetProtocol) { String servicePackageUuid; String spDescription = null; @@ -6595,7 +6618,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati s_logger.trace("Added service for the network offering: " + offService + " with provider " + provider.getName()); } - if (vpcOff) { + if (vpcOff && !forNsx) { final List supportedSvcs = new ArrayList(); supportedSvcs.addAll(serviceProviderMap.keySet()); _vpcMgr.validateNtwkOffForVpc(offering, supportedSvcs); diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index 7088933f584..6e6cfedc2a0 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -62,6 +62,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.query.QueryService; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -325,7 +326,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis svcProviderMap.put(svc, defaultProviders); } } - createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled, null, false, false, false); + createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, + true, State.Enabled, null, false, + false, false, false, null); } // configure default vpc offering with Netscaler as LB Provider @@ -344,7 +347,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis svcProviderMap.put(svc, defaultProviders); } } - createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false, false, false); + createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false, false, false, false, null); } @@ -364,12 +367,13 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis svcProviderMap.put(svc, defaultProviders); } } - createVpcOffering(VpcOffering.redundantVPCOfferingName, VpcOffering.redundantVPCOfferingName, svcProviderMap, true, State.Enabled, null, false, false, true); + createVpcOffering(VpcOffering.redundantVPCOfferingName, VpcOffering.redundantVPCOfferingName, svcProviderMap, true, State.Enabled, + null, false, false, true, false, null); } - // configure default vpc offering with NSX as network service provider - if (_vpcOffDao.findByUniqueName(VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME) == null) { - s_logger.debug("Creating default VPC offering with NSX as network service provider" + VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME); + // configure default vpc offering with NSX as network service provider in NAT mode + if (_vpcOffDao.findByUniqueName(VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME) == null) { + s_logger.debug("Creating default VPC offering with NSX as network service provider" + VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME); final Map> svcProviderMap = new HashMap>(); final Set defaultProviders = Set.of(Provider.Nsx); for (final Service svc : getSupportedServices()) { @@ -380,7 +384,26 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis svcProviderMap.put(svc, defaultProviders); } } - createVpcOffering(VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME, VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME, svcProviderMap, false, State.Enabled, null, false, false, false); + createVpcOffering(VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME, VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME, svcProviderMap, false, + State.Enabled, null, false, false, false, true, NetworkOffering.NsxMode.NATTED.name()); + + } + + // configure default vpc offering with NSX as network service provider in Route mode + if (_vpcOffDao.findByUniqueName(VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME) == null) { + s_logger.debug("Creating default VPC offering with NSX as network service provider" + VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME); + final Map> svcProviderMap = new HashMap>(); + final Set defaultProviders = Set.of(Provider.Nsx); + for (final Service svc : getSupportedServices()) { + if (List.of(Service.UserData, Service.Dhcp, Service.Dns).contains(svc)) { + final Set userDataProvider = Set.of(Provider.VPCVirtualRouter); + svcProviderMap.put(svc, userDataProvider); + } else { + svcProviderMap.put(svc, defaultProviders); + } + } + createVpcOffering(VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME, VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME, svcProviderMap, false, + State.Enabled, null, false, false, false, true, NetworkOffering.NsxMode.ROUTED.name()); } } @@ -440,7 +463,25 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis final Long serviceOfferingId = cmd.getServiceOfferingId(); final List domainIds = cmd.getDomainIds(); final List zoneIds = cmd.getZoneIds(); + final Boolean forNsx = cmd.isForNsx(); + String nsxMode = cmd.getNsxMode(); final boolean enable = cmd.getEnable(); + + if (Boolean.TRUE.equals(forNsx)) { + if (Objects.isNull(nsxMode)) { + throw new InvalidParameterValueException("Mode for an NSX offering needs to be specified.Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values())); + } + if (!EnumUtils.isValidEnum(NetworkOffering.NsxMode.class, nsxMode)) { + throw new InvalidParameterValueException("Invalid mode passed. Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values())); + } + } else { + if (Objects.nonNull(nsxMode)) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("nsxMode has is ignored for non-NSX enabled zones"); + } + nsxMode = null; + } + } // check if valid domain if (CollectionUtils.isNotEmpty(cmd.getDomainIds())) { for (final Long domainId: cmd.getDomainIds()) { @@ -463,14 +504,15 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } return createVpcOffering(vpcOfferingName, displayText, supportedServices, - serviceProviderList, serviceCapabilityList, internetProtocol, serviceOfferingId, + serviceProviderList, serviceCapabilityList, internetProtocol, serviceOfferingId, forNsx, nsxMode, domainIds, zoneIds, (enable ? State.Enabled : State.Disabled)); } @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_OFFERING_CREATE, eventDescription = "creating vpc offering", create = true) public VpcOffering createVpcOffering(final String name, final String displayText, final List supportedServices, final Map> serviceProviders, - final Map serviceCapabilityList, final NetUtils.InternetProtocol internetProtocol, final Long serviceOfferingId, List domainIds, List zoneIds, State state) { + final Map serviceCapabilityList, final NetUtils.InternetProtocol internetProtocol, final Long serviceOfferingId, + final Boolean forNsx, final String mode, List domainIds, List zoneIds, State state) { if (!Ipv6Service.Ipv6OfferingCreationEnabled.value() && !(internetProtocol == null || NetUtils.InternetProtocol.IPv4.equals(internetProtocol))) { throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for creating IPv6 supported VPC offering", Ipv6Service.Ipv6OfferingCreationEnabled.key())); @@ -555,7 +597,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis final boolean offersRegionLevelVPC = isVpcOfferingForRegionLevelVpc(serviceCapabilityList); final boolean redundantRouter = isVpcOfferingRedundantRouter(serviceCapabilityList); final VpcOfferingVO offering = createVpcOffering(name, displayText, svcProviderMap, false, state, serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC, - redundantRouter); + redundantRouter, forNsx, mode); if (offering != null) { List detailsVO = new ArrayList<>(); @@ -583,7 +625,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis @DB protected VpcOfferingVO createVpcOffering(final String name, final String displayText, final Map> svcProviderMap, final boolean isDefault, final State state, final Long serviceOfferingId, final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC, - final boolean redundantRouter) { + final boolean redundantRouter, Boolean forNsx, String mode) { return Transaction.execute(new TransactionCallback() { @Override @@ -594,6 +636,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis if (state != null) { offering.setState(state); } + offering.setForNsx(forNsx); + offering.setMode(mode); s_logger.debug("Adding vpc offering " + offering); offering = _vpcOffDao.persist(offering); // populate services and providers diff --git a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java index 75298b73e64..f7ada1fccf1 100644 --- a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java @@ -1206,17 +1206,34 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } _networkOfferingDao.persistDefaultL2NetworkOfferings(); - // Offering #9 - network offering for nsx provider - NetworkOfferingVO defaultNSXNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DEFAULT_NSX_OFFERING, "Offering for NSX enabled networks", + // Offering #9 - network offering for nsx provider - NATTED mode + NetworkOfferingVO defaultNatNSXNetworkOffering = + new NetworkOfferingVO(NetworkOffering.DEFAULT_NAT_NSX_OFFERING, "Offering for NSX enabled networks - NAT mode", TrafficType.Guest, false, false, null, null, true, Availability.Optional, null, GuestType.Isolated, false, false, false, false, false, true); - defaultNSXNetworkOffering.setForNsx(true); - defaultNSXNetworkOffering.setState(NetworkOffering.State.Enabled); - defaultNSXNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNSXNetworkOffering); + defaultNatNSXNetworkOffering.setForNsx(true); + defaultNatNSXNetworkOffering.setNsxMode(NetworkOffering.NsxMode.NATTED.name()); + defaultNatNSXNetworkOffering.setState(NetworkOffering.State.Enabled); + defaultNatNSXNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNatNSXNetworkOffering); for (Map.Entry service : defaultNSXNetworkOfferingProviders.entrySet()) { NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultNSXNetworkOffering.getId(), service.getKey(), service.getValue()); + new NetworkOfferingServiceMapVO(defaultNatNSXNetworkOffering.getId(), service.getKey(), service.getValue()); + _ntwkOfferingServiceMapDao.persist(offService); + s_logger.trace("Added service for the network offering: " + offService); + } + + // Offering #10 - network offering for nsx provider - ROUTED mode + NetworkOfferingVO defaultRouteNSXNetworkOffering = + new NetworkOfferingVO(NetworkOffering.DEFAULT_NAT_NSX_OFFERING, "Offering for NSX enabled networks - NAT mode", + TrafficType.Guest, false, false, null, null, true, Availability.Optional, null, GuestType.Isolated, false, false, false, false, false, true); + defaultRouteNSXNetworkOffering.setForNsx(true); + defaultRouteNSXNetworkOffering.setNsxMode(NetworkOffering.NsxMode.ROUTED.name()); + defaultRouteNSXNetworkOffering.setState(NetworkOffering.State.Enabled); + defaultRouteNSXNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultRouteNSXNetworkOffering); + + for (Map.Entry service : defaultNSXNetworkOfferingProviders.entrySet()) { + NetworkOfferingServiceMapVO offService = + new NetworkOfferingServiceMapVO(defaultRouteNSXNetworkOffering.getId(), service.getKey(), service.getValue()); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } diff --git a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java index 21bf3d57ff2..5b29061585c 100644 --- a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -546,7 +546,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu Integer networkRate, Map> serviceProviderMap, boolean isDefault, GuestType type, boolean systemOnly, Long serviceOfferingId, boolean conserveMode, Map> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent, Map details, boolean egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive, Boolean forVpc, - Boolean forTungsten, Boolean forNsx, List domainIds, List zoneIds, boolean enableOffering, NetUtils.InternetProtocol internetProtocol) { + Boolean forTungsten, Boolean forNsx, String mode, List domainIds, List zoneIds, boolean enableOffering, NetUtils.InternetProtocol internetProtocol) { // TODO Auto-generated method stub return null; } diff --git a/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java b/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java index 1038420f9a5..52885c43753 100644 --- a/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java +++ b/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java @@ -129,7 +129,7 @@ public class CreateNetworkOfferingTest extends TestCase { public void createSharedNtwkOffWithVlan() { NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, true, Availability.Optional, 200, null, false, Network.GuestType.Shared, false, - null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null); + null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null); assertNotNull("Shared network offering with specifyVlan=true failed to create ", off); } @@ -137,7 +137,7 @@ public class CreateNetworkOfferingTest extends TestCase { public void createSharedNtwkOffWithNoVlan() { NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, false, Availability.Optional, 200, null, false, Network.GuestType.Shared, - false, null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null); + false, null, false, null, true, false, null, false, null, true, false, false, false, null, null,null, false, null); assertNotNull("Shared network offering with specifyVlan=false was created", off); } @@ -145,7 +145,7 @@ public class CreateNetworkOfferingTest extends TestCase { public void createSharedNtwkOffWithSpecifyIpRanges() { NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, true, Availability.Optional, 200, null, false, Network.GuestType.Shared, false, - null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null); + null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null); assertNotNull("Shared network offering with specifyIpRanges=true failed to create ", off); } @@ -154,7 +154,7 @@ public class CreateNetworkOfferingTest extends TestCase { public void createSharedNtwkOffWithoutSpecifyIpRanges() { NetworkOfferingVO off = configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, true, Availability.Optional, 200, null, false, Network.GuestType.Shared, - false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, false, null); + false, null, false, null, false, false, null, false, null, true, false, false, false, null,null, null, false, null); assertNull("Shared network offering with specifyIpRanges=false was created", off); } @@ -167,7 +167,7 @@ public class CreateNetworkOfferingTest extends TestCase { serviceProviderMap.put(Network.Service.SourceNat, vrProvider); NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, false, Availability.Optional, 200, serviceProviderMap, false, - Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, false, null); + Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, null, false, null); assertNotNull("Isolated network offering with specifyIpRanges=false failed to create ", off); } @@ -180,7 +180,7 @@ public class CreateNetworkOfferingTest extends TestCase { serviceProviderMap.put(Network.Service.SourceNat, vrProvider); NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true, Availability.Optional, 200, serviceProviderMap, false, - Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, false, null); + Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null,null, null, false, null); assertNotNull("Isolated network offering with specifyVlan=true wasn't created", off); } @@ -193,7 +193,7 @@ public class CreateNetworkOfferingTest extends TestCase { serviceProviderMap.put(Network.Service.SourceNat, vrProvider); NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, false, Availability.Optional, 200, serviceProviderMap, false, - Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null); + Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null); assertNull("Isolated network offering with specifyIpRanges=true and source nat service enabled, was created", off); } @@ -204,7 +204,7 @@ public class CreateNetworkOfferingTest extends TestCase { Set vrProvider = new HashSet(); NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, false, Availability.Optional, 200, serviceProviderMap, false, - Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null); + Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null); assertNotNull("Isolated network offering with specifyIpRanges=true and with no sourceNatService, failed to create", off); } @@ -222,7 +222,7 @@ public class CreateNetworkOfferingTest extends TestCase { serviceProviderMap.put(Network.Service.Lb, vrProvider); NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true, Availability.Optional, 200, serviceProviderMap, false, - Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, false, null); + Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null, false, null); // System.out.println("Creating Vpc Network Offering"); assertNotNull("Vpc Isolated network offering with Vpc provider ", off); } @@ -242,7 +242,7 @@ public class CreateNetworkOfferingTest extends TestCase { serviceProviderMap.put(Network.Service.Lb, lbProvider); NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true, Availability.Optional, 200, serviceProviderMap, false, - Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, false, null); + Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null, false, null); // System.out.println("Creating Vpc Network Offering"); assertNotNull("Vpc Isolated network offering with Vpc and Netscaler provider ", off); } diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index aa3b843780b..43cb291e8db 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -871,6 +871,7 @@ "label.forceencap": "Force UDP encapsulation of ESP packets", "label.forgedtransmits": "Forged transmits", "label.format": "Format", +"label.fornsx": "NSX", "label.free": "Free", "label.french.azerty.keyboard": "French AZERTY keyboard", "label.friday": "Friday", @@ -1284,6 +1285,7 @@ "label.minorsequence": "Minor Sequence", "label.minsize": "Minimum size", "label.minute.past.hour": "minute(s) past the hour", +"label.mode": "Mode", "label.monday": "Monday", "label.monitor": "Monitor", "label.monitor.expected.code": "Expected HTTP Status Code", @@ -1377,6 +1379,8 @@ "label.not.found": "Not found", "label.not.suitable": "Not suitable", "label.notifications": "Notifications", +"label.nsx": "NSX", +"label.nsx.mode": "NSX Mode", "label.nsx.provider": "NSX Provider", "label.nsx.provider.name": "NSX provider name", "label.nsx.provider.hostname": "NSX provider hostname", @@ -1555,6 +1559,7 @@ "label.public.ips": "Public IP addresses", "label.public.lb": "Public LB", "label.public.traffic": "Public traffic", +"label.public.traffic.nsx": "NSX Public traffic", "label.publicinterface": "Public interface", "label.publicip": "IP address", "label.publicipid": "IP address ID", diff --git a/ui/src/components/CheckBoxSelectPair.vue b/ui/src/components/CheckBoxSelectPair.vue index de6aed473cb..4fba1da2556 100644 --- a/ui/src/components/CheckBoxSelectPair.vue +++ b/ui/src/components/CheckBoxSelectPair.vue @@ -21,6 +21,7 @@ {{ checkBoxLabel }} @@ -30,7 +31,8 @@ v-if="reversed !== checked" :label="selectLabel">
- {{ service.name }} : {{ service.provider[0].name }} + {{ service.name }} : {{ service.provider?.[0]?.name }}
diff --git a/ui/src/config/section/offering.js b/ui/src/config/section/offering.js index c44de61fb79..df4e264276b 100644 --- a/ui/src/config/section/offering.js +++ b/ui/src/config/section/offering.js @@ -262,7 +262,7 @@ export default { docHelp: 'adminguide/networking.html#network-offerings', permission: ['listNetworkOfferings'], columns: ['name', 'state', 'guestiptype', 'traffictype', 'networkrate', 'domain', 'zone', 'order'], - details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'internetprotocol', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'service', 'tags', 'domain', 'zone'], + details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'internetprotocol', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'forvpc', 'fornsx', 'nsxmode', 'service', 'tags', 'domain', 'zone'], resourceType: 'NetworkOffering', tabs: [ { @@ -355,7 +355,7 @@ export default { permission: ['listVPCOfferings'], resourceType: 'VpcOffering', columns: ['name', 'state', 'displaytext', 'domain', 'zone', 'order'], - details: ['name', 'id', 'displaytext', 'internetprotocol', 'distributedvpcrouter', 'tags', 'service', 'domain', 'zone', 'created'], + details: ['name', 'id', 'displaytext', 'internetprotocol', 'distributedvpcrouter', 'tags', 'service', 'fornsx', 'nsxmode', 'domain', 'zone', 'created'], related: [{ name: 'vpc', title: 'label.vpc', diff --git a/ui/src/views/offering/AddNetworkOffering.vue b/ui/src/views/offering/AddNetworkOffering.vue index 17359e4e0c0..5af0c000165 100644 --- a/ui/src/views/offering/AddNetworkOffering.vue +++ b/ui/src/views/offering/AddNetworkOffering.vue @@ -41,7 +41,7 @@ v-model:value="form.displaytext" :placeholder="apiParams.displaytext.description"/> - + @@ -60,10 +60,10 @@ {{ $t('label.isolated') }} - + {{ $t('label.l2') }} - + {{ $t('label.shared') }} @@ -93,7 +93,7 @@ - +