Skip to content

Commit 0f9efed

Browse files
Fix issue #3040: Broadcast URI not set to vxlan, but vlan
1 parent 5526342 commit 0f9efed

File tree

3 files changed

+122
-15
lines changed

3 files changed

+122
-15
lines changed

api/src/main/java/com/cloud/network/Networks.java

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.net.URISyntaxException;
2121

2222
import com.cloud.utils.exception.CloudRuntimeException;
23+
import org.apache.commons.lang3.StringUtils;
2324

2425
/**
2526
* Network includes all of the enums used within networking.
@@ -253,20 +254,42 @@ public static URI fromString(String candidate) {
253254
Long.parseLong(candidate);
254255
return Vlan.toUri(candidate);
255256
} catch (NumberFormatException nfe) {
256-
if (com.cloud.dc.Vlan.UNTAGGED.equalsIgnoreCase(candidate)) {
257-
return Native.toUri(candidate);
258-
}
259-
try {
260-
URI uri = new URI(candidate);
261-
BroadcastDomainType tiep = getSchemeValue(uri);
262-
if (tiep.scheme != null && tiep.scheme.equals(uri.getScheme())) {
263-
return uri;
264-
} else {
265-
throw new CloudRuntimeException("string '" + candidate + "' has an unknown BroadcastDomainType.");
266-
}
267-
} catch (URISyntaxException e) {
268-
throw new CloudRuntimeException("string is not a broadcast URI: " + candidate);
257+
return getVlanUriWhenNumberFormatException(candidate);
258+
}
259+
}
260+
261+
/**
262+
* This method is called in case of NumberFormatException is thrown when parsing the String into long
263+
*/
264+
private static URI getVlanUriWhenNumberFormatException(String candidate) {
265+
if(StringUtils.isBlank(candidate)) {
266+
throw new CloudRuntimeException("Expected VLAN or VXLAN but got a null isolation method");
267+
}
268+
if (com.cloud.dc.Vlan.UNTAGGED.equalsIgnoreCase(candidate)) {
269+
return Native.toUri(candidate);
270+
}
271+
try {
272+
URI uri = new URI(candidate);
273+
BroadcastDomainType tiep = getSchemeValue(uri);
274+
if (tiep.scheme != null && tiep.scheme.equals(uri.getScheme())) {
275+
return uri;
276+
} else {
277+
throw new CloudRuntimeException("string '" + candidate + "' has an unknown BroadcastDomainType.");
269278
}
279+
} catch (URISyntaxException e) {
280+
throw new CloudRuntimeException("string is not a broadcast URI: " + candidate);
281+
}
282+
}
283+
284+
/**
285+
* Encodes a string into a BroadcastUri, according to the given BroadcastDomainType
286+
*/
287+
public static URI encodeStringIntoBroadcastUri(String candidate, BroadcastDomainType isolationMethod) {
288+
try{
289+
Long.parseLong(candidate);
290+
return isolationMethod.toUri(candidate);
291+
} catch (NumberFormatException nfe) {
292+
return getVlanUriWhenNumberFormatException(candidate);
270293
}
271294
}
272295
};

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,7 +2279,7 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam
22792279
}
22802280

22812281
if (vlanSpecified) {
2282-
URI uri = BroadcastDomainType.fromString(vlanId);
2282+
URI uri = encodeVlanIdIntoBroadcastUri(vlanId, pNtwk);
22832283
//don't allow to specify vlan tag used by physical network for dynamic vlan allocation
22842284
if (!(bypassVlanOverlapCheck && ntwkOff.getGuestType() == GuestType.Shared) && _dcDao.findVnet(zoneId, pNtwk.getId(), BroadcastDomainType.getValue(uri)).size() > 0) {
22852285
throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
@@ -2424,7 +2424,7 @@ public Network doInTransaction(final TransactionStatus status) {
24242424
//Logical router's UUID provided as VLAN_ID
24252425
userNetwork.setVlanIdAsUUID(vlanIdFinal); //Set transient field
24262426
} else {
2427-
uri = BroadcastDomainType.fromString(vlanIdFinal);
2427+
uri = encodeVlanIdIntoBroadcastUri(vlanIdFinal, pNtwk);
24282428
}
24292429
userNetwork.setBroadcastUri(uri);
24302430
if (!vlanIdFinal.equalsIgnoreCase(Vlan.UNTAGGED)) {
@@ -2475,6 +2475,21 @@ public Network doInTransaction(final TransactionStatus status) {
24752475
return network;
24762476
}
24772477

2478+
/**
2479+
* Encodes VLAN/VXLAN ID into a Broadcast URI according to the isolation method from the Physical Network.
2480+
* @return Broadcast URI, e.g. 'vlan://vlan_ID' or 'vxlan://vlxan_ID'
2481+
*/
2482+
protected URI encodeVlanIdIntoBroadcastUri(String vlanId, PhysicalNetwork pNtwk) {
2483+
if(StringUtils.isNotBlank(pNtwk.getIsolationMethods().get(0))) {
2484+
String isolationMethod = pNtwk.getIsolationMethods().get(0).toLowerCase();
2485+
String vxlan = BroadcastDomainType.Vxlan.toString().toLowerCase();
2486+
if(isolationMethod.toLowerCase().equals(vxlan)) {
2487+
return BroadcastDomainType.encodeStringIntoBroadcastUri(vlanId, BroadcastDomainType.Vxlan);
2488+
}
2489+
}
2490+
return BroadcastDomainType.fromString(vlanId);
2491+
}
2492+
24782493
/**
24792494
* Checks bypass VLAN id/range overlap check during network creation for guest networks
24802495
* @param bypassVlanOverlapCheck bypass VLAN id/range overlap check

engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@
2222
import static org.mockito.Mockito.verify;
2323
import static org.mockito.Mockito.when;
2424

25+
import java.net.URI;
2526
import java.util.ArrayList;
2627
import java.util.Arrays;
2728
import java.util.HashMap;
2829
import java.util.List;
2930
import java.util.Map;
3031

32+
import com.cloud.network.dao.PhysicalNetworkVO;
33+
import com.cloud.utils.exception.CloudRuntimeException;
3134
import org.apache.log4j.Logger;
3235
import org.junit.Assert;
3336
import org.junit.Before;
@@ -463,4 +466,70 @@ public void validateLockedRequestedIpTestFreeAndNotNullIp() {
463466
testOrchastrator.validateLockedRequestedIp(ipVoSpy, lockedIp);
464467
}
465468

469+
@Test
470+
public void encodeVlanIdIntoBroadcastUriTestVxlan() {
471+
encodeVlanIdIntoBroadcastUriPrepareAndTest("123", "VXLAN", "vxlan", "vxlan://123");
472+
}
473+
474+
@Test
475+
public void encodeVlanIdIntoBroadcastUriTestVlan() {
476+
encodeVlanIdIntoBroadcastUriPrepareAndTest("123", "VLAN", "vlan", "vlan://123");
477+
}
478+
479+
@Test
480+
public void encodeVlanIdIntoBroadcastUriTestEmpty() {
481+
encodeVlanIdIntoBroadcastUriPrepareAndTest("123", "", "vlan", "vlan://123");
482+
}
483+
484+
@Test
485+
public void encodeVlanIdIntoBroadcastUriTestNull() {
486+
encodeVlanIdIntoBroadcastUriPrepareAndTest("123", null, "vlan", "vlan://123");
487+
}
488+
489+
@Test(expected = CloudRuntimeException.class)
490+
public void encodeVlanIdIntoBroadcastUriTestEmptyVlanId() {
491+
encodeVlanIdIntoBroadcastUriPrepareAndTest("", "vxlan", "vlan", "vlan://123");
492+
}
493+
494+
@Test(expected = CloudRuntimeException.class)
495+
public void encodeVlanIdIntoBroadcastUriTestNullVlanId() {
496+
encodeVlanIdIntoBroadcastUriPrepareAndTest(null, "vlan", "vlan", "vlan://123");
497+
}
498+
499+
@Test(expected = CloudRuntimeException.class)
500+
public void encodeVlanIdIntoBroadcastUriTestBlankVlanId() {
501+
encodeVlanIdIntoBroadcastUriPrepareAndTest(" ", "vlan", "vlan", "vlan://123");
502+
}
503+
504+
@Test
505+
public void encodeVlanIdIntoBroadcastUriTestNullVlanIdWithSchema() {
506+
encodeVlanIdIntoBroadcastUriPrepareAndTest("vlan://123", "vlan", "vlan", "vlan://123");
507+
}
508+
509+
@Test
510+
public void encodeVlanIdIntoBroadcastUriTestNullVlanIdWithSchemaIsolationVxlan() {
511+
encodeVlanIdIntoBroadcastUriPrepareAndTest("vlan://123", "vxlan", "vlan", "vlan://123");
512+
}
513+
514+
@Test
515+
public void encodeVlanIdIntoBroadcastUriTestNullVxlanIdWithSchema() {
516+
encodeVlanIdIntoBroadcastUriPrepareAndTest("vxlan://123", "vxlan", "vxlan", "vxlan://123");
517+
}
518+
519+
@Test
520+
public void encodeVlanIdIntoBroadcastUriTestNullVxlanIdWithSchemaIsolationVlan() {
521+
encodeVlanIdIntoBroadcastUriPrepareAndTest("vxlan://123", "vlan", "vxlan", "vxlan://123");
522+
}
523+
524+
private void encodeVlanIdIntoBroadcastUriPrepareAndTest(String vlanId, String isolationMethod, String expectedIsolation, String expectedUri) {
525+
PhysicalNetworkVO physicalNetwork = new PhysicalNetworkVO();
526+
List<String> isolationMethods = new ArrayList<>();
527+
isolationMethods.add(isolationMethod);
528+
physicalNetwork.setIsolationMethods(isolationMethods);
529+
530+
URI resultUri = testOrchastrator.encodeVlanIdIntoBroadcastUri(vlanId, physicalNetwork);
531+
532+
Assert.assertEquals(expectedIsolation, resultUri.getScheme());
533+
Assert.assertEquals(expectedUri, resultUri.toString());
534+
}
466535
}

0 commit comments

Comments
 (0)