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 f0838cdd309 [VMware] Update vlans with proper range before creating port group for dvSwitch (#10708) f0838cdd309 is described below commit f0838cdd30984818919c12663dec6effa26483c7 Author: Suresh Kumar Anaparti <sureshkumar.anapa...@gmail.com> AuthorDate: Thu May 8 12:18:14 2025 +0530 [VMware] Update vlans with proper range before creating port group for dvSwitch (#10708) --- .../src/main/java/com/cloud/utils/StringUtils.java | 92 +++++++++++++++++++++- .../hypervisor/vmware/mo/HypervisorHostHelper.java | 22 ++++-- .../vmware/mo/HypervisorHostHelperTest.java | 56 ++++++++++++- 3 files changed, 159 insertions(+), 11 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/StringUtils.java b/utils/src/main/java/com/cloud/utils/StringUtils.java index 01b6f833271..c6116123b40 100644 --- a/utils/src/main/java/com/cloud/utils/StringUtils.java +++ b/utils/src/main/java/com/cloud/utils/StringUtils.java @@ -28,6 +28,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -90,7 +92,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { /** * Converts a List of tags to a comma separated list - * @param tags + * @param tagsList * @return String containing a comma separated list of tags */ @@ -304,4 +306,92 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { return mapResult; } + + /** + * Converts the comma separated numbers to ranges for any consecutive numbers in the input with numbers (and ranges) + * Eg: "198,200-203,299,300,301,303,304,305,306,307,308,311,197" to "197-198,200-203,299-301,303-308,311" + * @param inputNumbersAndRanges + * @return String containing a converted ranges for any consecutive numbers + */ + public static String numbersToRange(String inputNumbersAndRanges) { + Set<Integer> numberSet = new TreeSet<>(); + for (String inputNumber : inputNumbersAndRanges.split(",")) { + inputNumber = inputNumber.trim(); + if (inputNumber.contains("-")) { + String[] range = inputNumber.split("-"); + if (range.length == 2 && range[0] != null && range[1] != null) { + int start = NumbersUtil.parseInt(range[0], 0); + int end = NumbersUtil.parseInt(range[1], 0); + for (int i = start; i <= end; i++) { + numberSet.add(i); + } + } + } else { + numberSet.add(NumbersUtil.parseInt(inputNumber, 0)); + } + } + + StringBuilder result = new StringBuilder(); + if (!numberSet.isEmpty()) { + List<Integer> numbers = new ArrayList<>(numberSet); + int startNumber = numbers.get(0); + int endNumber = startNumber; + + for (int i = 1; i < numbers.size(); i++) { + if (numbers.get(i) == endNumber + 1) { + endNumber = numbers.get(i); + } else { + appendRange(result, startNumber, endNumber); + startNumber = endNumber = numbers.get(i); + } + } + appendRange(result, startNumber, endNumber); + } + + return result.toString(); + } + + private static void appendRange(StringBuilder sb, int startNumber, int endNumber) { + if (sb.length() > 0) { + sb.append(","); + } + if (startNumber == endNumber) { + sb.append(startNumber); + } else { + sb.append(startNumber).append("-").append(endNumber); + } + } + + /** + * Converts the comma separated numbers and ranges to numbers + * Eg: "197-198,200-203,299-301,303-308,311" to "197,198,200,201,202,203,299,300,301,303,304,305,306,307,308,311" + * @param inputNumbersAndRanges + * @return String containing a converted numbers + */ + public static String rangeToNumbers(String inputNumbersAndRanges) { + Set<Integer> numberSet = new TreeSet<>(); + for (String inputNumber : inputNumbersAndRanges.split(",")) { + inputNumber = inputNumber.trim(); + if (inputNumber.contains("-")) { + String[] range = inputNumber.split("-"); + int startNumber = Integer.parseInt(range[0]); + int endNumber = Integer.parseInt(range[1]); + for (int i = startNumber; i <= endNumber; i++) { + numberSet.add(i); + } + } else { + numberSet.add(Integer.parseInt(inputNumber)); + } + } + + StringBuilder result = new StringBuilder(); + for (int number : numberSet) { + if (result.length() > 0) { + result.append(","); + } + result.append(number); + } + + return result.toString(); + } } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index 44965e9321b..e43af246696 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -274,16 +274,18 @@ public class HypervisorHostHelper { } } - public static String composeCloudNetworkName(String prefix, String vlanId, String svlanId, Integer networkRateMbps, String vSwitchName) { + public static String composeCloudNetworkName(String prefix, String vlanId, String svlanId, Integer networkRateMbps, String vSwitchName, VirtualSwitchType vSwitchType) { StringBuffer sb = new StringBuffer(prefix); if (vlanId == null || UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) { sb.append(".untagged"); } else { + if (vSwitchType != VirtualSwitchType.StandardVirtualSwitch && StringUtils.containsAny(vlanId, ",-")) { + vlanId = com.cloud.utils.StringUtils.numbersToRange(vlanId); + } sb.append(".").append(vlanId); if (svlanId != null) { sb.append(".").append("s" + svlanId); } - } if (networkRateMbps != null && networkRateMbps.intValue() > 0) @@ -293,7 +295,12 @@ public class HypervisorHostHelper { sb.append(".").append(VersioningContants.PORTGROUP_NAMING_VERSION); sb.append("-").append(vSwitchName); - return sb.toString(); + String networkName = sb.toString(); + if (networkName.length() > 80) { + // the maximum limit for a vSwitch name is 80 chars, applies to both standard and distributed virtual switches. + s_logger.warn(String.format("The network name: %s for the vSwitch %s of type %s, exceeds 80 chars", networkName, vSwitchName, vSwitchType)); + } + return networkName; } public static Map<String, String> getValidatedVsmCredentials(VmwareContext context) throws Exception { @@ -595,7 +602,7 @@ public class HypervisorHostHelper { if (vlanId != null) { vlanId = vlanId.replace("vlan://", ""); } - networkName = composeCloudNetworkName(namePrefix, vlanId, secondaryvlanId, networkRateMbps, physicalNetwork); + networkName = composeCloudNetworkName(namePrefix, vlanId, secondaryvlanId, networkRateMbps, physicalNetwork, vSwitchType); if (vlanId != null && !UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId) && !StringUtils.containsAny(vlanId, ",-")) { createGCTag = true; @@ -1167,8 +1174,9 @@ public class HypervisorHostHelper { if (vlanId == null && vlanRange != null && !vlanRange.isEmpty()) { s_logger.debug("Creating dvSwitch port vlan-trunk spec with range: " + vlanRange); VmwareDistributedVirtualSwitchTrunkVlanSpec trunkVlanSpec = new VmwareDistributedVirtualSwitchTrunkVlanSpec(); - for (final String vlanRangePart : vlanRange.split(",")) { - if (vlanRangePart == null || vlanRange.isEmpty()) { + String vlanRangeUpdated = com.cloud.utils.StringUtils.numbersToRange(vlanRange); + for (final String vlanRangePart : vlanRangeUpdated.split(",")) { + if (vlanRangePart == null || vlanRangePart.isEmpty()) { continue; } final NumericRange numericRange = new NumericRange(); @@ -1320,7 +1328,7 @@ public class HypervisorHostHelper { // No doubt about this, depending on vid=null to avoid lots of code below vid = null; } else { - networkName = composeCloudNetworkName(namePrefix, vlanId, null, networkRateMbps, vSwitchName); + networkName = composeCloudNetworkName(namePrefix, vlanId, null, networkRateMbps, vSwitchName, VirtualSwitchType.StandardVirtualSwitch); if (vlanId != null && !UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) { createGCTag = true; diff --git a/vmware-base/src/test/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java b/vmware-base/src/test/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java index 1c888a05748..05fb9c9e6d3 100644 --- a/vmware-base/src/test/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java +++ b/vmware-base/src/test/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelperTest.java @@ -557,7 +557,7 @@ public class HypervisorHostHelperTest { networkRateMbps = 200; prefix = "cloud.public"; vSwitchName = "vSwitch0"; - String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, svlanId, networkRateMbps, vSwitchName); + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, svlanId, networkRateMbps, vSwitchName, VirtualSwitchType.StandardVirtualSwitch); assertEquals("cloud.public.100.200.1-vSwitch0", cloudNetworkName); } @@ -567,7 +567,7 @@ public class HypervisorHostHelperTest { networkRateMbps = null; prefix = "cloud.storage"; vSwitchName = "vSwitch1"; - String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, svlanId, networkRateMbps, vSwitchName); + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, svlanId, networkRateMbps, vSwitchName, VirtualSwitchType.StandardVirtualSwitch); assertEquals("cloud.storage.untagged.0.1-vSwitch1", cloudNetworkName); } @@ -578,10 +578,60 @@ public class HypervisorHostHelperTest { networkRateMbps = 512; prefix = "cloud.guest"; vSwitchName = "vSwitch2"; - String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, svlanId, networkRateMbps, vSwitchName); + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, svlanId, networkRateMbps, vSwitchName, VirtualSwitchType.StandardVirtualSwitch); assertEquals("cloud.guest.400.s123.512.1-vSwitch2", cloudNetworkName); } + @Test + public void testComposeCloudNetworkNameVlanRangeGuestTrafficDvSwitch() { + vlanId = "400-500"; + networkRateMbps = 512; + prefix = "cloud.guest"; + vSwitchName = "dvSwitch0"; + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, null, networkRateMbps, vSwitchName, VirtualSwitchType.VMwareDistributedVirtualSwitch); + assertEquals("cloud.guest.400-500.512.1-dvSwitch0", cloudNetworkName); + } + + @Test + public void testComposeCloudNetworkNameVlanNumbersGuestTrafficDvSwitch() { + vlanId = "3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020"; + networkRateMbps = 512; + prefix = "cloud.guest"; + vSwitchName = "dvSwitch0"; + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, null, networkRateMbps, vSwitchName, VirtualSwitchType.VMwareDistributedVirtualSwitch); + assertEquals("cloud.guest.3001-3020.512.1-dvSwitch0", cloudNetworkName); + } + + @Test + public void testComposeCloudNetworkNameVlanNumbersAndRangeGuestTrafficDvSwitch() { + vlanId = "3001,3004-3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3020"; + networkRateMbps = 512; + prefix = "cloud.guest"; + vSwitchName = "dvSwitch0"; + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, null, networkRateMbps, vSwitchName, VirtualSwitchType.VMwareDistributedVirtualSwitch); + assertEquals("cloud.guest.3001,3004-3018,3020.512.1-dvSwitch0", cloudNetworkName); + } + + @Test + public void testComposeCloudNetworkNameUnorderedVlanNumbersAndRangeGuestTrafficDvSwitch() { + vlanId = "3018,3020,3011,3012,3004-3006,3007,3001,3008,3009,3010,3013,3014,3015,3016,3017"; + networkRateMbps = 512; + prefix = "cloud.guest"; + vSwitchName = "dvSwitch0"; + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, null, networkRateMbps, vSwitchName, VirtualSwitchType.VMwareDistributedVirtualSwitch); + assertEquals("cloud.guest.3001,3004-3018,3020.512.1-dvSwitch0", cloudNetworkName); + } + + @Test + public void testComposeCloudNetworkNameOverlappingVlanNumbersAndRangeGuestTrafficDvSwitch() { + vlanId = "3018,3020,3011,3012,3004-3006,3007,3001,3008,3009,3010,3013,3014,3015,3016,3017,3005-3008"; + networkRateMbps = 512; + prefix = "cloud.guest"; + vSwitchName = "dvSwitch0"; + String cloudNetworkName = HypervisorHostHelper.composeCloudNetworkName(prefix, vlanId, null, networkRateMbps, vSwitchName, VirtualSwitchType.VMwareDistributedVirtualSwitch); + assertEquals("cloud.guest.3001,3004-3018,3020.512.1-dvSwitch0", cloudNetworkName); + } + @Test public void testOvfDomRewriter() { final String ovfString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +