Skip to content

Commit a5c80e4

Browse files
committed
Clean up persistent VXLAN network bridges on all hosts on network delete
1 parent 8eeccdb commit a5c80e4

4 files changed

Lines changed: 81 additions & 4 deletions

File tree

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,9 +1515,10 @@ private void setupPersistentNetwork(NetworkVO network, NetworkOfferingVO offerin
15151515
}
15161516
}
15171517

1518-
private boolean networkMeetsPersistenceCriteria(NetworkVO network, NetworkOfferingVO offering, boolean cleanup) {
1519-
boolean criteriaMet = offering.isPersistent() &&
1520-
(network.getBroadcastUri() != null && BroadcastDomainType.getSchemeValue(network.getBroadcastUri()) == BroadcastDomainType.Vlan);
1518+
protected boolean networkMeetsPersistenceCriteria(NetworkVO network, NetworkOfferingVO offering, boolean cleanup) {
1519+
BroadcastDomainType broadcastDomainType = BroadcastDomainType.getSchemeValue(network.getBroadcastUri());
1520+
List<BroadcastDomainType> broadcastTypes = Arrays.asList(BroadcastDomainType.Vlan, BroadcastDomainType.Vxlan);
1521+
boolean criteriaMet = offering.isPersistent() && broadcastTypes.contains(broadcastDomainType);
15211522
if (!cleanup) {
15221523
return criteriaMet && network.getGuestType() == GuestType.L2;
15231524
} else {

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import com.cloud.network.Network.GuestType;
6060
import com.cloud.network.Network.Service;
6161
import com.cloud.network.NetworkModel;
62+
import com.cloud.network.Networks.BroadcastDomainType;
6263
import com.cloud.network.Networks.TrafficType;
6364
import com.cloud.network.dao.IPAddressDao;
6465
import com.cloud.network.dao.IPAddressVO;
@@ -1010,4 +1011,33 @@ public void testImportNicWithIP4Address() throws Exception {
10101011
assertEquals("testtag", nicProfile.getName());
10111012
}
10121013
}
1014+
1015+
private NetworkVO mockPersistentNetwork(URI broadcastUri, GuestType guestType) {
1016+
NetworkVO network = mock(NetworkVO.class);
1017+
when(network.getBroadcastUri()).thenReturn(broadcastUri);
1018+
when(network.getGuestType()).thenReturn(guestType);
1019+
return network;
1020+
}
1021+
1022+
@Test
1023+
public void testNetworkMeetsPersistenceCriteriaForVlanAndVxlan() {
1024+
NetworkOfferingVO offering = mock(NetworkOfferingVO.class);
1025+
when(offering.isPersistent()).thenReturn(true);
1026+
1027+
NetworkVO vlanNetwork = mockPersistentNetwork(BroadcastDomainType.Vlan.toUri(100), GuestType.Isolated);
1028+
NetworkVO vxlanNetwork = mockPersistentNetwork(BroadcastDomainType.Vxlan.toUri(5000), GuestType.Isolated);
1029+
1030+
assertTrue(testOrchestrator.networkMeetsPersistenceCriteria(vlanNetwork, offering, true));
1031+
assertTrue(testOrchestrator.networkMeetsPersistenceCriteria(vxlanNetwork, offering, true));
1032+
}
1033+
1034+
@Test
1035+
public void testNetworkMeetsPersistenceCriteriaForNonPersistentOffering() {
1036+
NetworkOfferingVO offering = mock(NetworkOfferingVO.class);
1037+
when(offering.isPersistent()).thenReturn(false);
1038+
1039+
NetworkVO vxlanNetwork = mockPersistentNetwork(BroadcastDomainType.Vxlan.toUri(5000), GuestType.Isolated);
1040+
1041+
assertFalse(testOrchestrator.networkMeetsPersistenceCriteria(vxlanNetwork, offering, true));
1042+
}
10131043
}

‎plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/BridgeVifDriver.java‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ private void createVnet(String vnetId, String pif, String brName, String protoco
343343
}
344344
}
345345

346-
private void deleteVnetBr(String brName, boolean deleteBr) {
346+
protected void deleteVnetBr(String brName, boolean deleteBr) {
347347
synchronized (_vnetBridgeMonitor) {
348348
String cmdout = Script.runSimpleBashScript("ls /sys/class/net/" + brName);
349349
if (cmdout == null)
@@ -458,6 +458,14 @@ public boolean isExistingBridge(String bridgeName) {
458458

459459
@Override
460460
public void deleteBr(NicTO nic) {
461+
if (Networks.BroadcastDomainType.getSchemeValue(nic.getBroadcastUri()) == Networks.BroadcastDomainType.Vxlan) {
462+
// VXLAN bridges are named after the VNI alone, so no physical interface lookup is needed
463+
String vxlanId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
464+
if (vxlanId != null) {
465+
deleteVnetBr(generateVxnetBrName(null, vxlanId), true);
466+
}
467+
return;
468+
}
461469
String vlanId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
462470
String trafficLabel = nic.getName();
463471
String pifName = _pifs.get(trafficLabel);

‎plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/BridgeVifDriverTest.java‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@
1818

1919
import java.net.URI;
2020
import java.net.URISyntaxException;
21+
import java.util.HashMap;
2122

2223
import org.junit.Assert;
2324
import org.junit.Test;
2425
import org.junit.runner.RunWith;
2526
import org.mockito.InjectMocks;
27+
import org.mockito.MockedConstruction;
2628
import org.mockito.Mockito;
2729
import org.mockito.Spy;
2830
import org.mockito.junit.MockitoJUnitRunner;
2931

3032
import com.cloud.agent.api.to.NicTO;
3133
import com.cloud.exception.InternalErrorException;
3234
import com.cloud.network.Networks;
35+
import com.cloud.utils.script.Script;
3336

3437
@RunWith(MockitoJUnitRunner.class)
3538
public class BridgeVifDriverTest {
@@ -100,4 +103,39 @@ public void createStorageVnetBridgeIfNeededCreatesVnetBridgeWhenUntaggedVlan() t
100103
String result = driver.createStorageVnetBridgeIfNeeded(nic, "trafficLabel", BRIDGE_NAME);
101104
Assert.assertEquals(BRIDGE_NAME, result);
102105
}
106+
107+
private String createAndDeleteBridge(String vNetId, String trafficLabel, Networks.BroadcastDomainType broadcastType) throws InternalErrorException {
108+
Mockito.doNothing().when(driver).deleteVnetBr(Mockito.anyString(), Mockito.anyBoolean());
109+
String createdBridge;
110+
try (MockedConstruction<Script> ignored = Mockito.mockConstruction(Script.class)) {
111+
createdBridge = driver.createVnetBr(vNetId, trafficLabel, broadcastType.scheme());
112+
}
113+
114+
NicTO nic = new NicTO();
115+
nic.setName(trafficLabel);
116+
nic.setBroadcastUri(broadcastType.toUri(vNetId));
117+
driver.deleteBr(nic);
118+
return createdBridge;
119+
}
120+
121+
@Test
122+
public void deleteBrRemovesTheBridgeCreatedForVxlan() throws InternalErrorException {
123+
driver._pifs = new HashMap<>();
124+
125+
String createdBridge = createAndDeleteBridge("5000", "unknownTrafficLabel", Networks.BroadcastDomainType.Vxlan);
126+
127+
Assert.assertEquals("brvx-5000", createdBridge);
128+
Mockito.verify(driver).deleteVnetBr(createdBridge, true);
129+
}
130+
131+
@Test
132+
public void deleteBrRemovesTheBridgeCreatedForVlan() throws InternalErrorException {
133+
driver._pifs = new HashMap<>();
134+
driver._pifs.put("guestLabel", "eth1");
135+
136+
String createdBridge = createAndDeleteBridge("100", "guestLabel", Networks.BroadcastDomainType.Vlan);
137+
138+
Assert.assertEquals("breth1-100", createdBridge);
139+
Mockito.verify(driver).deleteVnetBr(createdBridge, true);
140+
}
103141
}

0 commit comments

Comments
 (0)