diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 1b634d5b904b..9bdb3305a9c1 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -34,6 +34,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -43,7 +44,9 @@ import com.cloud.dc.VlanDetailsVO; import com.cloud.dc.dao.VlanDetailsDao; +import com.cloud.network.dao.NsxProviderDao; import com.cloud.network.dao.PublicIpQuarantineDao; +import com.cloud.network.element.NsxProviderVO; import com.cloud.offering.ServiceOffering; import com.cloud.service.dao.ServiceOfferingDao; import org.apache.cloudstack.acl.ControlledEntity.ACLType; @@ -410,6 +413,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C ServiceOfferingDao serviceOfferingDao; @Inject PublicIpQuarantineDao publicIpQuarantineDao; + @Inject + NsxProviderDao nsxProviderDao; @Autowired @Qualifier("networkHelper") @@ -1472,6 +1477,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac _accountMgr.checkAccess(owner, ntwkOff, zone); validateZoneAvailability(caller, zone); + validateNetworkCreationSupported(zone.getId(), zone.getName(), ntwkOff.getGuestType()); ACLType aclType = getAclType(caller, cmd.getAclType(), ntwkOff); @@ -1728,6 +1734,15 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac return network; } + private void validateNetworkCreationSupported(long zoneId, String zoneName, GuestType guestType) { + NsxProviderVO nsxProviderVO = nsxProviderDao.findByZoneId(zoneId); + if (Objects.nonNull(nsxProviderVO) && List.of(GuestType.L2, GuestType.Shared).contains(guestType)) { + throw new InvalidParameterValueException( + String.format("Creation of %s networks is not supported in NSX enabled zone %s", guestType.name(), zoneName) + ); + } + } + void checkAndSetRouterSourceNatIp(Account owner, CreateNetworkCmd cmd, Network network) throws InsufficientAddressCapacityException, ResourceAllocationException { String sourceNatIp = cmd.getSourceNatIP(); if (sourceNatIp == null) { diff --git a/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java b/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java index c993f7b7095e..f2ab2a08ae75 100644 --- a/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java +++ b/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java @@ -40,6 +40,7 @@ import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; +import com.cloud.network.dao.NsxProviderDao; import com.cloud.network.dao.PublicIpQuarantineDao; import com.cloud.network.vo.PublicIpQuarantineVO; import com.cloud.user.dao.AccountDao; @@ -212,6 +213,8 @@ public class NetworkServiceImplTest { @Mock private Ip ipMock; + @Mock + private NsxProviderDao nsxProviderDao; private static Date beforeDate; @@ -295,6 +298,7 @@ public void setup() throws Exception { service.commandSetupHelper = commandSetupHelper; service.networkHelper = networkHelper; service._ipAddrMgr = ipAddressManagerMock; + service.nsxProviderDao = nsxProviderDao; callContextMocked = Mockito.mockStatic(CallContext.class); CallContext callContextMock = Mockito.mock(CallContext.class); callContextMocked.when(CallContext::current).thenReturn(callContextMock); diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index be035adc4ba2..d6559243f71e 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2969,6 +2969,7 @@ "message.kubernetes.cluster.stop": "Please confirm that you want to stop the cluster.", "message.kubernetes.cluster.upgrade": "Please select new Kubernetes version.", "message.kubernetes.version.delete": "Please confirm that you want to delete this Kubernetes version.", +"message.l2.network.unsupported.for.nsx": "L2 networks aren't supported for NSX enabled zones", "message.launch.zone": "Zone is ready to launch; please proceed to the next step.", "message.launch.zone.description": "Zone is ready to launch; please proceed to the next step.", "message.launch.zone.hint": "Configure Network components and traffic including IP addresses.", @@ -3116,6 +3117,7 @@ "message.setup.physical.network.during.zone.creation": "When adding a zone, you need to set up one or more physical Networks. Each Network corresponds to a NIC on the hypervisor. Each physical Network can carry one or more types of traffic, with certain restrictions on how they may be combined. Add or remove one or more traffic types onto each physical Network.", "message.setup.physical.network.during.zone.creation.basic": "When adding a basic zone, you can set up one physical Network, which corresponds to a NIC on the hypervisor. The Network carries several types of traffic.

You may also add other traffic types onto the physical Network.", "message.shared.network.offering.warning": "Domain admins and regular Users can only create shared Networks from Network offering with the setting specifyvlan=false. Please contact an administrator to create a Network offering if this list is empty.", +"message.shared.network.unsupported.for.nsx": "Shared networks aren't supported for NSX enabled zones", "message.shutdown.triggered": "A shutdown has been triggered. CloudStack will not accept new jobs", "message.snapshot.additional.zones": "Snapshots will always be created in its native zone - %x, here you can select additional zone(s) where it will be copied to at creation time", "message.sourcenatip.change.warning": "WARNING: Changing the sourcenat IP address of the network will cause connectivity downtime for the Instances with NICs in the Network.", diff --git a/ui/src/views/network/CreateIsolatedNetworkForm.vue b/ui/src/views/network/CreateIsolatedNetworkForm.vue index 8336277a702d..437630e10ead 100644 --- a/ui/src/views/network/CreateIsolatedNetworkForm.vue +++ b/ui/src/views/network/CreateIsolatedNetworkForm.vue @@ -573,6 +573,9 @@ export default { this.selectedNetworkOffering = {} api('listNetworkOfferings', params).then(json => { this.networkOfferings = json.listnetworkofferingsresponse.networkoffering + if (this.selectedZone.isnsxenabled) { + this.networkOfferings = this.networkOfferings.filter(offering => offering.fornsx) + } }).catch(error => { this.$notifyError(error) }).finally(() => { diff --git a/ui/src/views/network/CreateL2NetworkForm.vue b/ui/src/views/network/CreateL2NetworkForm.vue index 76695eb625f9..6bb87e178f31 100644 --- a/ui/src/views/network/CreateL2NetworkForm.vue +++ b/ui/src/views/network/CreateL2NetworkForm.vue @@ -18,7 +18,14 @@