Fix: install additional rules on SG and GW to realize VM migration
Change-Id: I221a5c0e8c53273c70f49f606121cd95b8529d87
(cherry picked from commit ef487901f479d6218199e95ee41fd57ac1cc7359)
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java
index 53fefc9..2797f32 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java
@@ -30,6 +30,8 @@
import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
import org.onosproject.kubevirtnetworking.api.KubevirtPort;
+import org.onosproject.kubevirtnetworking.api.KubevirtPortEvent;
+import org.onosproject.kubevirtnetworking.api.KubevirtPortListener;
import org.onosproject.kubevirtnetworking.api.KubevirtPortService;
import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
import org.onosproject.kubevirtnetworking.api.KubevirtRouterEvent;
@@ -133,6 +135,9 @@
private final InternalNodeListener kubevirtNodeListener =
new InternalNodeListener();
+ private final InternalPortListener kubevirtPortListener =
+ new InternalPortListener();
+
@Activate
protected void activate() {
appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
@@ -140,6 +145,7 @@
leadershipService.runForLeadership(appId.name());
kubevirtRouterService.addListener(kubevirtRouterListener);
kubevirtNodeService.addListener(kubevirtNodeListener);
+ kubevirtPortService.addListener(kubevirtPortListener);
log.info("Started");
}
@@ -149,6 +155,7 @@
leadershipService.withdraw(appId.name());
kubevirtRouterService.removeListener(kubevirtRouterListener);
kubevirtNodeService.removeListener(kubevirtNodeListener);
+ kubevirtPortService.removeListener(kubevirtPortListener);
eventExecutor.shutdown();
@@ -220,6 +227,14 @@
.findAny().orElse(null);
}
+ private KubevirtFloatingIp getFloatingIpByKubevirtPort(KubevirtPort port) {
+
+ return kubevirtRouterService.floatingIps().stream()
+ .filter(fip -> port.ipAddress().equals(fip.fixedIp()))
+ .filter(fip -> port.vmName().equals(fip.vmName()))
+ .findAny().orElse(null);
+ }
+
private void setFloatingIpUpstreamRules(KubevirtRouter router,
KubevirtFloatingIp floatingIp,
KubevirtPort port,
@@ -493,4 +508,53 @@
}
}
}
+
+ private class InternalPortListener implements KubevirtPortListener {
+
+ private boolean isRelevantHelper() {
+ return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
+ }
+
+ @Override
+ public void event(KubevirtPortEvent event) {
+ switch (event.type()) {
+ case KUBEVIRT_PORT_MIGRATED:
+ eventExecutor.execute(() -> processPortMigration(event.subject()));
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ }
+
+ private void processPortMigration(KubevirtPort port) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ KubevirtFloatingIp fip = getFloatingIpByKubevirtPort(port);
+ if (fip == null) {
+ return;
+ }
+
+ KubevirtRouter router = kubevirtRouterService.router(fip.routerName());
+ if (router == null) {
+ log.warn("The router {} is not found", fip.routerName());
+ return;
+ }
+
+ String gateway = router.electedGateway();
+ KubevirtNode node = kubevirtNodeService.node(gateway);
+
+ if (node == null) {
+ log.warn("The gateway node {} is not found", gateway);
+ return;
+ }
+
+ setFloatingIpRulesForFip(router, fip, node, true);
+
+ log.info("Configure floating IP {} on gateway {}",
+ fip.floatingIp().toString(), node.hostname());
+ }
+ }
}
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java
index 2c35b74..b51af25 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java
@@ -51,11 +51,8 @@
import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
import org.onosproject.kubevirtnode.api.KubevirtNodeService;
import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -199,9 +196,6 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected KubevirtSecurityGroupService securityGroupService;
- private final DeviceListener deviceListener =
- new InternalDeviceListener();
-
private final KubevirtPortListener portListener =
new InternalKubevirtPortListener();
private final KubevirtSecurityGroupListener securityGroupListener =
@@ -221,7 +215,6 @@
protected void activate() {
appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
localNodeId = clusterService.getLocalNode().id();
- deviceService.addListener(deviceListener);
securityGroupService.addListener(securityGroupListener);
portService.addListener(portListener);
networkService.addListener(networkListener);
@@ -238,7 +231,6 @@
configService.unregisterProperties(getClass(), false);
nodeService.removeListener(nodeListener);
networkService.removeListener(networkListener);
- deviceService.removeListener(deviceListener);
eventExecutor.shutdown();
log.info("Stopped");
@@ -278,7 +270,7 @@
}
private void initializeConnTrackTable(DeviceId deviceId, int ctTable,
- int forwardTable, boolean install) {
+ int forwardTable, boolean install) {
// table={ACL_INGRESS_TABLE(44)},ip,ct_state=-trk, actions=ct(table:{ACL_CT_TABLE(45)})
long ctState = computeCtStateFlag(false, false, false);
@@ -304,7 +296,7 @@
}
private void initializeTenantAclTable(KubevirtNetwork network,
- DeviceId deviceId, boolean install) {
+ DeviceId deviceId, boolean install) {
// FIXME: in bridge initialization phase, some patch ports may not be
// available until they are created, we wait for a while ensure all
// patch ports are created via network bootstrap
@@ -313,7 +305,7 @@
break;
} else {
log.info("Wait for tenant patch ports creation for device {} " +
- "and network {}", deviceId, network.networkId());
+ "and network {}", deviceId, network.networkId());
waitFor(5);
}
}
@@ -355,7 +347,7 @@
}
private void initializeEgressTable(DeviceId deviceId, int egressTable,
- int forwardTable, boolean install) {
+ int forwardTable, boolean install) {
if (install) {
flowRuleService.setUpTableMissEntry(deviceId, TENANT_ACL_EGRESS_TABLE);
} else {
@@ -534,21 +526,21 @@
});
TrafficSelector tSelector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchEthDst(port.macAddress())
- .matchIPDst(IpPrefix.valueOf(port.ipAddress(), 32))
- .build();
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchEthDst(port.macAddress())
+ .matchIPDst(IpPrefix.valueOf(port.ipAddress(), 32))
+ .build();
TrafficTreatment tTreatment = DefaultTrafficTreatment.builder()
- .transition(TENANT_ACL_INGRESS_TABLE)
- .build();
+ .transition(TENANT_ACL_INGRESS_TABLE)
+ .build();
flowRuleService.setRule(appId,
- deviceId,
- tSelector,
- tTreatment,
- PRIORITY_ACL_RULE,
- TENANT_ACL_RECIRC_TABLE,
- install);
+ deviceId,
+ tSelector,
+ tTreatment,
+ PRIORITY_ACL_RULE,
+ TENANT_ACL_RECIRC_TABLE,
+ install);
}
/**
@@ -920,6 +912,10 @@
case KUBEVIRT_PORT_DEVICE_ADDED:
eventExecutor.execute(() -> processPortDeviceAdded(event));
break;
+ case KUBEVIRT_PORT_MIGRATED:
+ eventExecutor.execute(() -> processPortDeviceAdded(event));
+ eventExecutor.execute(() -> processOldPortRemove(event));
+ break;
default:
// do nothing for the other events
break;
@@ -932,7 +928,7 @@
}
if (event.securityGroupId() == null ||
- securityGroupService.securityGroup(event.securityGroupId()) == null) {
+ securityGroupService.securityGroup(event.securityGroupId()) == null) {
return;
}
@@ -952,7 +948,7 @@
}
if (event.securityGroupId() == null ||
- securityGroupService.securityGroup(event.securityGroupId()) == null) {
+ securityGroupService.securityGroup(event.securityGroupId()) == null) {
return;
}
@@ -978,7 +974,23 @@
updateSecurityGroupRule(port, sgRule, false);
});
log.info("Removed security group {} from port {}",
- sgStr, event.subject().macAddress());
+ sgStr, event.subject().macAddress());
+ }
+ }
+
+ private void processOldPortRemove(KubevirtPortEvent event) {
+ if (!isRelevantHelper(event)) {
+ return;
+ }
+
+ KubevirtPort oldPort = event.oldSubject();
+ for (String sgStr : oldPort.securityGroups()) {
+ KubevirtSecurityGroup sg = securityGroupService.securityGroup(sgStr);
+ sg.rules().forEach(sgRule -> {
+ updateSecurityGroupRule(oldPort, sgRule, false);
+ });
+ log.info("Removed security group {} from port {}",
+ sgStr, event.subject().macAddress());
}
}
@@ -1120,53 +1132,6 @@
}
}
- /**
- * An internal OVS listener. This listener is used for listening the network
- * facing events from OVS device. If a new OVS device is detected, discovered,
- * ONOS tries to install device related rules into the target kubernetes node.
- */
- private class InternalDeviceListener implements DeviceListener {
-
- @Override
- public boolean isRelevant(DeviceEvent event) {
- return event.subject().type() == Device.Type.SWITCH;
- }
-
- private boolean isRelevantHelper() {
- return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
- }
-
- @Override
- public void event(DeviceEvent event) {
- Device device = event.subject();
-
- switch (event.type()) {
- case DEVICE_AVAILABILITY_CHANGED:
- case DEVICE_ADDED:
- eventExecutor.execute(() -> {
- if (!isRelevantHelper()) {
- return;
- }
-
- KubevirtNode node = nodeService.node(device.id());
-
- if (node == null) {
- return;
- }
-
- if (deviceService.isAvailable(device.id())) {
- resetSecurityGroupRulesByNode(node);
- }
- });
- break;
- case DEVICE_REMOVED:
- default:
- // do nothing
- break;
- }
- }
- }
-
private void resetSecurityGroupRulesByNode(KubevirtNode node) {
if (getUseSecurityGroupFlag()) {
initializeProviderPipeline(node, true);
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java
index 414fa9e..4e1121a 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java
@@ -226,7 +226,7 @@
if (existing != null) {
if (port.deviceId() != null) {
- if (existing.deviceId() == null || existing.deviceId() != port.deviceId()) {
+ if (existing.deviceId() == null || !existing.deviceId().equals(port.deviceId())) {
KubevirtPort updated = existing.updateDeviceId(port.deviceId());
// internally we update device ID of kubevirt port
portAdminService.updatePort(updated);