Dynamically add or remove gateway node according to GW annotation

Change-Id: Ic7ac799eda0c1d028e934cc1bfd07af34e714e18
(cherry picked from commit 91358d6126e13adcc4e4b8c7bbd46179fb4c2913)
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 26e27ff..96d111c 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
@@ -37,6 +37,8 @@
 import org.onosproject.kubevirtnetworking.api.KubevirtRouterService;
 import org.onosproject.kubevirtnetworking.util.RulePopulatorUtil;
 import org.onosproject.kubevirtnode.api.KubevirtNode;
+import org.onosproject.kubevirtnode.api.KubevirtNodeEvent;
+import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
 import org.onosproject.kubevirtnode.api.KubevirtNodeService;
 import org.onosproject.net.Device;
 import org.onosproject.net.PortNumber;
@@ -118,15 +120,19 @@
     private ApplicationId appId;
     private NodeId localNodeId;
 
-    private final InternalRouterEventListener kubevirtRouterlistener =
+    private final InternalRouterEventListener kubevirtRouterListener =
             new InternalRouterEventListener();
 
+    private final InternalNodeEventListener kubevirtNodeListener =
+            new InternalNodeEventListener();
+
     @Activate
     protected void activate() {
         appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
         localNodeId = clusterService.getLocalNode().id();
         leadershipService.runForLeadership(appId.name());
-        kubevirtRouterService.addListener(kubevirtRouterlistener);
+        kubevirtRouterService.addListener(kubevirtRouterListener);
+        kubevirtNodeService.addListener(kubevirtNodeListener);
 
         log.info("Started");
     }
@@ -134,7 +140,8 @@
     @Deactivate
     protected void deactivate() {
         leadershipService.withdraw(appId.name());
-        kubevirtRouterService.removeListener(kubevirtRouterlistener);
+        kubevirtRouterService.removeListener(kubevirtRouterListener);
+        kubevirtNodeService.removeListener(kubevirtNodeListener);
 
         eventExecutor.shutdown();
 
@@ -204,6 +211,7 @@
                 PRE_FLAT_TABLE,
                 install);
     }
+
     private KubevirtPort getKubevirtPort(KubevirtFloatingIp floatingIp) {
 
         return kubevirtPortService.ports().stream()
@@ -352,7 +360,6 @@
             return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
         }
 
-
         @Override
         public void event(KubevirtRouterEvent event) {
             switch (event.type()) {
@@ -385,4 +392,44 @@
             setFloatingIpRules(router, floatingIp, false);
         }
     }
+
+    private class InternalNodeEventListener implements KubevirtNodeListener {
+
+        private boolean isRelevantHelper() {
+            return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
+        }
+
+        @Override
+        public void event(KubevirtNodeEvent event) {
+            switch (event.type()) {
+                case KUBEVIRT_NODE_COMPLETE:
+                    eventExecutor.execute(() -> processNodeCompletion(event.subject()));
+                    break;
+                case KUBEVIRT_NODE_REMOVED:
+                case KUBEVIRT_NODE_INCOMPLETE:
+                default:
+                    break;
+            }
+        }
+
+        private void processNodeCompletion(KubevirtNode node) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+
+            kubevirtRouterService.floatingIps().forEach(fip -> {
+                KubevirtRouter router = kubevirtRouterService.router(fip.routerName());
+                if (router != null) {
+                    KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
+                    if (electedGw == null) {
+                        return;
+                    }
+
+                    if (electedGw.hostname().equals(node.hostname())) {
+                        setFloatingIpRules(router, fip, true);
+                    }
+                }
+            });
+        }
+    }
 }