Skip to content

Commit 2cc200d

Browse files
committed
Fixing vlan allowed to be created with existing pvlan id
1 parent 910d9f7 commit 2cc200d

5 files changed

Lines changed: 60 additions & 0 deletions

File tree

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,6 +2498,12 @@ public Network doInTransaction(final TransactionStatus status) {
24982498
} else {
24992499
uri = BroadcastDomainType.fromString(vlanIdFinal);
25002500
}
2501+
2502+
if (_networksDao.listByPhysicalNetworkPvlan(physicalNetworkId, uri.toString()).size() > 0) {
2503+
throw new InvalidParameterValueException("Network with vlan " + vlanIdFinal +
2504+
" already exists or overlaps with other network pvlans in zone " + zoneId);
2505+
}
2506+
25012507
userNetwork.setBroadcastUri(uri);
25022508
if (!vlanIdFinal.equalsIgnoreCase(Vlan.UNTAGGED)) {
25032509
userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan);

engine/schema/src/main/java/com/cloud/network/dao/NetworkDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,6 @@ public interface NetworkDao extends GenericDao<NetworkVO, Long>, StateDao<State,
126126
List<NetworkVO> listByAccountIdNetworkName(long accountId, String name);
127127

128128
List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType);
129+
130+
List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri);
129131
}

engine/schema/src/main/java/com/cloud/network/dao/NetworkDaoImpl.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,11 @@ protected boolean isNetworkOverlappingRequestedPvlan(Integer existingPrimaryVlan
761761
return exactMatch || secondaryVlanUsed || primaryVlanUsed || isolatedMax || promiscuousMax;
762762
}
763763

764+
// True when a VLAN ID overlaps with an existing PVLAN primary or secondary ID
765+
protected boolean isNetworkOverlappingRequestedPvlan(Integer existingPrimaryVlan, Integer existingSecondaryVlan, Integer requestedVlan) {
766+
return requestedVlan.equals(existingPrimaryVlan) || requestedVlan.equals(existingSecondaryVlan);
767+
}
768+
764769
protected Network.PVlanType getNetworkPvlanType(long networkId, List<Integer> existingPvlan) {
765770
Network.PVlanType existingPvlanType = null;
766771
NetworkDetailVO pvlanTypeDetail = networkDetailsDao.findDetail(networkId, ApiConstants.ISOLATED_PVLAN_TYPE);
@@ -772,6 +777,38 @@ protected Network.PVlanType getNetworkPvlanType(long networkId, List<Integer> ex
772777
return existingPvlanType;
773778
}
774779

780+
@Override
781+
public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri) {
782+
final URI searchUri = BroadcastDomainType.fromString(broadcastUri);
783+
if (!searchUri.getScheme().equalsIgnoreCase("vlan")) {
784+
throw new CloudRuntimeException("VLAN requested but URI is not in the expected format: " + searchUri.toString());
785+
}
786+
final String searchRange = BroadcastDomainType.getValue(searchUri);
787+
final List<Integer> searchVlans = UriUtils.expandVlanUri(searchRange);
788+
final List<NetworkVO> overlappingNetworks = new ArrayList<>();
789+
790+
final SearchCriteria<NetworkVO> sc = PhysicalNetworkSearch.create();
791+
sc.setParameters("physicalNetworkId", physicalNetworkId);
792+
793+
for (final NetworkVO network : listBy(sc)) {
794+
if (network.getBroadcastUri() == null || !network.getBroadcastUri().getScheme().equalsIgnoreCase("pvlan")) {
795+
continue;
796+
}
797+
// Ensure existing and proposed VLAN don't overlap
798+
final String networkVlanRange = BroadcastDomainType.getValue(network.getBroadcastUri());
799+
if (networkVlanRange == null || networkVlanRange.isEmpty()) {
800+
continue;
801+
}
802+
List<Integer> existingPvlan = UriUtils.expandPvlanUri(networkVlanRange);
803+
if (isNetworkOverlappingRequestedPvlan(existingPvlan.get(0), existingPvlan.get(1), searchVlans.get(0))) {
804+
overlappingNetworks.add(network);
805+
break;
806+
}
807+
}
808+
809+
return overlappingNetworks;
810+
}
811+
775812
@Override
776813
public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType) {
777814
final URI searchUri = BroadcastDomainType.fromString(broadcastUri);

server/src/test/java/com/cloud/network/dao/NetworkDaoTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,14 @@ public void testNetworkOverlappingMultipleCommunityAllowed() {
5252
Assert.assertFalse(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, Network.PVlanType.Community,
5353
existingPrimaryVlan, requestedVlan, Network.PVlanType.Community));
5454
}
55+
56+
public void testNetworkOverlappingVlanPvlanTrue() {
57+
Assert.assertTrue(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, existingPrimaryVlan));
58+
Assert.assertTrue(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, existingSecondaryVlan));
59+
}
60+
61+
public void testNetworkOverlappingVlanPvlanFalse() {
62+
Assert.assertFalse(dao.isNetworkOverlappingRequestedPvlan(existingPrimaryVlan, existingSecondaryVlan, requestedVlan));
63+
}
64+
5565
}

server/src/test/java/com/cloud/vpc/dao/MockNetworkDaoImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,9 @@ public List<NetworkVO> listByAccountIdNetworkName(final long accountId, final St
250250
public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType) {
251251
return null;
252252
}
253+
254+
@Override
255+
public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri) {
256+
return null;
257+
}
253258
}

0 commit comments

Comments
 (0)