[ONOS-5176] Refactoring: improves SONA pipeline and OpenstackRoutingManager

Change-Id: I6e582fff781c2e69fb6ef4b34d8e41767202fc20
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java
index 58b89a6..a373ff0 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java
@@ -25,6 +25,9 @@
 import org.onosproject.net.host.HostEvent;
 import org.onosproject.net.host.HostListener;
 import org.onosproject.net.host.HostService;
+import org.onosproject.openstackinterface.OpenstackInterfaceService;
+import org.onosproject.openstackinterface.OpenstackRouter;
+import org.onosproject.openstackinterface.OpenstackSubnet;
 import org.slf4j.Logger;
 
 import java.util.Objects;
@@ -50,6 +53,7 @@
     protected CoreService coreService;
     protected MastershipService mastershipService;
     protected HostService hostService;
+    protected OpenstackInterfaceService openstackService;
 
     protected HostListener hostListener = new InternalHostListener();
 
@@ -57,6 +61,7 @@
         ServiceDirectory services = new DefaultServiceDirectory();
         coreService = services.get(CoreService.class);
         mastershipService = services.get(MastershipService.class);
+        openstackService = services.get(OpenstackInterfaceService.class);
         hostService = services.get(HostService.class);
         hostService.addListener(hostListener);
 
@@ -107,6 +112,28 @@
                 .findFirst();
     }
 
+    protected Set<Host> getHosts(OpenstackSubnet osSubnet) {
+        return Tools.stream(hostService.getHosts())
+                .filter(host -> host.annotations().value(SUBNET_ID).equals(osSubnet.id()))
+                .collect(Collectors.toSet());
+    }
+
+    protected Optional<OpenstackRouter> getRouter(Host host) {
+        return openstackService.routers().stream()
+                .filter(router -> routableSubNets(router.id()).stream()
+                        .filter(subnet -> subnet.id().equals(host.annotations().value(SUBNET_ID)))
+                        .findAny().isPresent())
+                .findAny();
+    }
+
+    protected Set<OpenstackSubnet> routableSubNets(String osRouterId) {
+        return openstackService.ports().stream()
+                .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
+                        p.deviceId().equals(osRouterId))
+                .map(p -> openstackService.subnet(p.fixedIps().keySet().stream().findFirst().get()))
+                .collect(Collectors.toSet());
+    }
+
     protected Ip4Address getIp(Host host) {
         return host.ipAddresses().stream().findFirst().get().getIp4Address();
     }
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java
index d220b8c..3326417 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java
@@ -21,8 +21,8 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
 import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.instructions.ExtensionPropertyException;
 import org.onosproject.net.flow.instructions.ExtensionTreatment;
 import org.onosproject.net.flowobjective.DefaultForwardingObjective;
@@ -74,29 +74,36 @@
     }
 
     /**
-     * Removes flow rules with the supplied information.
+     * Adds flow rules with the supplied information.
      *
      * @param flowObjectiveService flow objective service
      * @param appId application id
      * @param deviceId device id to remove this flow rule
      * @param selector traffic selector
+     * @param treatment traffic treatment
      * @param flag flag
      * @param priority priority
+     * @param install populate flows if true, remove them otherwise
      */
-    public static void removeRule(FlowObjectiveService flowObjectiveService,
-                           ApplicationId appId,
-                           DeviceId deviceId,
-                           TrafficSelector selector,
-                           ForwardingObjective.Flag flag,
-                           int priority) {
-        ForwardingObjective fo = DefaultForwardingObjective.builder()
+    public static void setRule(FlowObjectiveService flowObjectiveService,
+                               ApplicationId appId,
+                               DeviceId deviceId,
+                               TrafficSelector selector,
+                               TrafficTreatment treatment,
+                               ForwardingObjective.Flag flag,
+                               int priority,
+                               boolean install) {
+        ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
                 .withSelector(selector)
-                .withTreatment(DefaultTrafficTreatment.builder().build())
+                .withTreatment(treatment)
                 .withFlag(flag)
                 .withPriority(priority)
-                .fromApp(appId)
-                .remove();
+                .fromApp(appId);
 
-        flowObjectiveService.forward(deviceId, fo);
+        if (install) {
+            flowObjectiveService.forward(deviceId, foBuilder.add());
+        } else {
+            flowObjectiveService.forward(deviceId, foBuilder.remove());
+        }
     }
 }