[ONOS-3804] [ONOS-3805] Initial L3 flowrules setup for Compute/Gateway nodes and PNAT Handler for OpenstackRouting

 - Performs app refactoring (openstackrouting and openstackswitching)
 - Implements L3 REST call corresponding openstackRouter and openstackRouterInterface.
 - Implements initail L3 rules population to compute/gateway node.
 - Implements PNAT rules population corresponding packet-in event.
 - Fixs comments and javadocs.
 - Rebases on master.

Change-Id: I5ad68810f50dc977737d30c43150c892b978b7cb
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
index 2ea5935..ab8c386 100644
--- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
+++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
@@ -29,6 +29,8 @@
 import org.onlab.packet.MacAddress;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
@@ -55,14 +57,14 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onlab.util.Tools.groupedThreads;
 
-@Service
 @Component(immediate = true)
+@Service
 /**
  * Populates flow rules about L3 functionality for VMs in Openstack.
  */
 public class OpenstackRoutingManager implements OpenstackRoutingService {
-    private final Logger log = LoggerFactory
-            .getLogger(getClass());
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected CoreService coreService;
@@ -86,6 +88,12 @@
     private Map<String, OpenstackRouterInterface> routerInterfaceMap = Maps.newHashMap();
     private Map<Integer, String> portNumMap = initPortNumMap();
     private static final String APP_ID = "org.onosproject.openstackrouting";
+    private static final String PORT_NAME = "portName";
+    private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface";
+
+    // TODO: This will be replaced to get the information from openstackswitchingservice.
+    private static final String EXTERNAL_INTERFACE_NAME = "veth0";
+
     private Map<Integer, String> initPortNumMap() {
         Map<Integer, String> map = Maps.newHashMap();
         for (int i = 1024; i < 65535; i++) {
@@ -104,7 +112,7 @@
     protected void activate() {
         appId = coreService.registerApplication(APP_ID);
         packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
-
+        reloadInitL3Rules();
         log.info("onos-openstackrouting started");
     }
 
@@ -150,7 +158,7 @@
         routerInterfaceMap.putIfAbsent(routerInterface.portId(), routerInterface);
         List<OpenstackRouterInterface> routerInterfaces = Lists.newArrayList();
         routerInterfaces.add(routerInterface);
-        checkExternalConnection(getOpenstackRouter(routerInterface.tenantId()), routerInterfaces);
+        checkExternalConnection(getOpenstackRouter(routerInterface.portId()), routerInterfaces);
     }
 
     @Override
@@ -160,6 +168,27 @@
         rulePopulator.removeExternalRules(routerInterface);
         routerInterfaceMap.remove(routerInterface.portId());
     }
+
+    private void reloadInitL3Rules() {
+        openstackService.ports()
+                .stream()
+                .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
+                .forEach(p -> {
+                    OpenstackRouterInterface routerInterface = portToRouterInterface(p);
+                    updateRouterInterface(routerInterface);
+                });
+    }
+
+    private OpenstackRouterInterface portToRouterInterface(OpenstackPort p) {
+        OpenstackRouterInterface.Builder osBuilder = new OpenstackRouterInterface.Builder()
+                .id(checkNotNull(p.id()))
+                .tenantId(checkNotNull(openstackService.network(p.networkId()).tenantId()))
+                .subnetId(checkNotNull(p.fixedIps().keySet().stream().findFirst().orElse(null)).toString())
+                .portId(checkNotNull(p.deviceId()));
+
+        return osBuilder.build();
+    }
+
     private class InternalPacketProcessor implements PacketProcessor {
 
         @Override
@@ -183,10 +212,15 @@
                         break;
                     default:
                         int portNum = getPortNum(ethernet.getSourceMAC(), iPacket.getDestinationAddress());
+                        Port port = getExternalPort(pkt.receivedFrom().deviceId(), EXTERNAL_INTERFACE_NAME);
+                        if (port == null) {
+                            log.warn("There`s no external interface");
+                            break;
+                        }
                         OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(),
                                 Ip4Address.valueOf(iPacket.getSourceAddress()));
                         l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context,
-                                portNum, openstackPort));
+                                portNum, openstackPort, port));
                         break;
                 }
 
@@ -201,24 +235,30 @@
         }
     }
 
+    private Port getExternalPort(DeviceId deviceId, String interfaceName) {
+        return deviceService.getPorts(deviceId)
+                .stream()
+                .filter(p -> p.annotations().value(PORT_NAME).equals(interfaceName))
+                .findAny()
+                .orElse(null);
+    }
+
     private void checkExternalConnection(OpenstackRouter router,
                                          Collection<OpenstackRouterInterface> routerInterfaces) {
         checkNotNull(router, "Router can not be null");
-        checkNotNull(routerInterfaces, "RouterInterfaces can not be null");
+        checkNotNull(routerInterfaces, "routerInterfaces can not be null");
         Ip4Address externalIp = router.gatewayExternalInfo().externalFixedIps()
                 .values().stream().findFirst().orElse(null);
         if ((externalIp == null) || (!router.gatewayExternalInfo().isEnablePnat())) {
-            log.debug("Failed to set pnat configuration");
+            log.debug("Not satisfied to set pnat configuration");
             return;
         }
-        routerInterfaces.forEach(routerInterface -> {
-            initiateL3Rule(router, routerInterface);
-        });
+        routerInterfaces.forEach(routerInterface -> initiateL3Rule(router, routerInterface));
     }
 
     private void initiateL3Rule(OpenstackRouter router, OpenstackRouterInterface routerInterface) {
         long vni = Long.parseLong(openstackService.network(openstackService
-                .port(routerInterface.portId()).networkId()).segmentId());
+                .port(routerInterface.id()).networkId()).segmentId());
         OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId,
                 openstackService, flowObjectiveService, deviceService, driverService);
         rulePopulator.populateExternalRules(vni, router, routerInterface);
@@ -229,15 +269,15 @@
                 .collect(Collectors.toList());
     }
 
-    private OpenstackRouter getOpenstackRouter(String tenantId) {
+    private OpenstackRouter getOpenstackRouter(String id) {
         return openstackService.routers().stream().filter(r ->
-                r.tenantId().equals(tenantId)).findFirst().orElse(null);
+                r.id().equals(id)).findAny().orElse(null);
     }
 
     private OpenstackPort getOpenstackPort(MacAddress sourceMac, Ip4Address ip4Address) {
-        OpenstackPort openstackPort = openstackService.ports("").stream()
+        OpenstackPort openstackPort = openstackService.ports().stream()
                 .filter(p -> p.macAddress().equals(sourceMac)).findFirst().orElse(null);
-        return openstackPort.fixedIps().values().stream().findFirst().orElse(null)
+        return checkNotNull(openstackPort.fixedIps().values().stream().findFirst().orElse(null))
                 .equals(ip4Address) ? openstackPort : null;
     }