This is an automated email from the ASF dual-hosted git repository. dahn pushed a commit to branch 4.19 in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.19 by this push: new 13ab8a04d13 Fix for Vlan doesn't match issue while adding IP range for the shared network without any IP range (#10837) 13ab8a04d13 is described below commit 13ab8a04d1384db5e07d75cc27c6894866b1f316 Author: Suresh Kumar Anaparti <sureshkumar.anapa...@gmail.com> AuthorDate: Fri May 16 12:54:55 2025 +0530 Fix for Vlan doesn't match issue while adding IP range for the shared network without any IP range (#10837) --- .../command/admin/vlan/CreateVlanIpRangeCmd.java | 3 - .../configuration/ConfigurationManagerImpl.java | 106 ++++++++++++++------- .../configuration/ConfigurationManagerTest.java | 6 ++ 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java index 66aefd46966..feef18bbed1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java @@ -155,9 +155,6 @@ public class CreateVlanIpRangeCmd extends BaseCmd { } public String getVlan() { - if (vlan == null || vlan.isEmpty()) { - vlan = "untagged"; - } return vlan; } diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 94a0fd2ea0d..b90d94dad5d 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -4407,14 +4407,24 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String endIP = cmd.getEndIp(); final String newVlanGateway = cmd.getGateway(); final String newVlanNetmask = cmd.getNetmask(); + Long networkId = cmd.getNetworkID(); + Long physicalNetworkId = cmd.getPhysicalNetworkId(); + + // Verify that network exists + Network network = getNetwork(networkId); + if (network != null) { + zoneId = network.getDataCenterId(); + physicalNetworkId = network.getPhysicalNetworkId(); + } + String vlanId = cmd.getVlan(); + vlanId = verifyAndUpdateVlanId(vlanId, network); + // TODO decide if we should be forgiving or demand a valid and complete URI if (!(vlanId == null || "".equals(vlanId) || vlanId.startsWith(BroadcastDomainType.Vlan.scheme()))) { vlanId = BroadcastDomainType.Vlan.toUri(vlanId).toString(); } final Boolean forVirtualNetwork = cmd.isForVirtualNetwork(); - Long networkId = cmd.getNetworkID(); - Long physicalNetworkId = cmd.getPhysicalNetworkId(); final String accountName = cmd.getAccountName(); final Long projectId = cmd.getProjectId(); final Long domainId = cmd.getDomainId(); @@ -4487,18 +4497,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - // Verify that network exists - Network network = null; - if (networkId != null) { - network = _networkDao.findById(networkId); - if (network == null) { - throw new InvalidParameterValueException("Unable to find network by id " + networkId); - } else { - zoneId = network.getDataCenterId(); - physicalNetworkId = network.getPhysicalNetworkId(); - } - } - // Verify that zone exists final DataCenterVO zone = _zoneDao.findById(zoneId); if (zone == null) { @@ -4639,6 +4637,32 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati ip6Cidr, domain, vlanOwner, network, sameSubnet); } + private Network getNetwork(Long networkId) { + if (networkId == null) { + return null; + } + + Network network = _networkDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Unable to find network by id " + networkId); + } + + return network; + } + + private String verifyAndUpdateVlanId(String vlanId, Network network) { + if (!StringUtils.isBlank(vlanId)) { + return vlanId; + } + + if (network == null || network.getTrafficType() != TrafficType.Guest) { + return Vlan.UNTAGGED; + } + + boolean connectivityWithoutVlan = isConnectivityWithoutVlan(network); + return getNetworkVlanId(network, connectivityWithoutVlan); + } + private Vlan commitVlan(final Long zoneId, final Long podId, final String startIP, final String endIP, final String newVlanGatewayFinal, final String newVlanNetmaskFinal, final String vlanId, final Boolean forVirtualNetwork, final Boolean forSystemVms, final Long networkId, final Long physicalNetworkId, final String startIPv6, final String endIPv6, final String ip6Gateway, final String ip6Cidr, final Domain domain, final Account vlanOwner, final Network network, final Pair<Boolean, Pair<String, String>> sameSubnet) { @@ -4847,28 +4871,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // same as network's vlan // 2) if vlan is missing, default it to the guest network's vlan if (network.getTrafficType() == TrafficType.Guest) { - String networkVlanId = null; - boolean connectivityWithoutVlan = false; - if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Connectivity)) { - Map<Capability, String> connectivityCapabilities = _networkModel.getNetworkServiceCapabilities(network.getId(), Service.Connectivity); - connectivityWithoutVlan = MapUtils.isNotEmpty(connectivityCapabilities) && connectivityCapabilities.containsKey(Capability.NoVlan); - } - - final URI uri = network.getBroadcastUri(); - if (connectivityWithoutVlan) { - networkVlanId = network.getBroadcastDomainType().toUri(network.getUuid()).toString(); - } else if (uri != null) { - // Do not search for the VLAN tag when the network doesn't support VLAN - if (uri.toString().startsWith("vlan")) { - final String[] vlan = uri.toString().split("vlan:\\/\\/"); - networkVlanId = vlan[1]; - // For pvlan - if (network.getBroadcastDomainType() != BroadcastDomainType.Vlan) { - networkVlanId = networkVlanId.split("-")[0]; - } - } - } - + boolean connectivityWithoutVlan = isConnectivityWithoutVlan(network); + String networkVlanId = getNetworkVlanId(network, connectivityWithoutVlan); if (vlanId != null && !connectivityWithoutVlan) { // if vlan is specified, throw an error if it's not equal to // network's vlanId @@ -5000,6 +5004,36 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return vlan; } + private boolean isConnectivityWithoutVlan(Network network) { + boolean connectivityWithoutVlan = false; + if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Connectivity)) { + Map<Capability, String> connectivityCapabilities = _networkModel.getNetworkServiceCapabilities(network.getId(), Service.Connectivity); + connectivityWithoutVlan = MapUtils.isNotEmpty(connectivityCapabilities) && connectivityCapabilities.containsKey(Capability.NoVlan); + } + return connectivityWithoutVlan; + } + + private String getNetworkVlanId(Network network, boolean connectivityWithoutVlan) { + String networkVlanId = null; + if (connectivityWithoutVlan) { + return network.getBroadcastDomainType().toUri(network.getUuid()).toString(); + } + + final URI uri = network.getBroadcastUri(); + if (uri != null) { + // Do not search for the VLAN tag when the network doesn't support VLAN + if (uri.toString().startsWith("vlan")) { + final String[] vlan = uri.toString().split("vlan:\\/\\/"); + networkVlanId = vlan[1]; + // For pvlan + if (network.getBroadcastDomainType() != BroadcastDomainType.Vlan) { + networkVlanId = networkVlanId.split("-")[0]; + } + } + } + return networkVlanId; + } + private void checkZoneVlanIpOverlap(DataCenterVO zone, Network network, String newCidr, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) { // Throw an exception if this subnet overlaps with subnet on other VLAN, // if this is ip range extension, gateway, network mask should be same and ip range should not overlap diff --git a/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java b/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java index 4b9441dd2ea..f8ae83078c4 100644 --- a/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java +++ b/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java @@ -54,6 +54,8 @@ import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.Ipv6GuestPrefixSubnetNetworkMapDao; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.offering.DiskOffering; @@ -189,6 +191,8 @@ public class ConfigurationManagerTest { @Mock HostPodDao _podDao; @Mock + NetworkDao _networkDao; + @Mock PhysicalNetworkDao _physicalNetworkDao; @Mock ImageStoreDao _imageStoreDao; @@ -1325,6 +1329,8 @@ public class ConfigurationManagerTest { public void testWrongIpv6CreateVlanAndPublicIpRange() { CreateVlanIpRangeCmd cmd = Mockito.mock(CreateVlanIpRangeCmd.class); Mockito.when(cmd.getIp6Cidr()).thenReturn("fd17:5:8a43:e2a4:c000::/66"); + NetworkVO network = Mockito.mock(NetworkVO.class); + Mockito.when(_networkDao.findById(Mockito.anyLong())).thenReturn(network); try { configurationMgr.createVlanAndPublicIpRange(cmd); } catch (InsufficientCapacityException | ResourceUnavailableException | ResourceAllocationException e) {