[ONOS-7553] Support injecting physical interfaces to openstack node

Change-Id: I5d746e9b4fa6015dbaec90d27ea7e1a7fa105e31
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
index 939b628..025757e 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
@@ -59,6 +59,7 @@
 import org.onosproject.openstacknode.api.OpenstackNodeHandler;
 import org.onosproject.openstacknode.api.OpenstackNodeListener;
 import org.onosproject.openstacknode.api.OpenstackNodeService;
+import org.onosproject.openstacknode.api.OpenstackPhyInterface;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
 import org.onosproject.ovsdb.controller.OvsdbController;
 import org.onosproject.ovsdb.controller.OvsdbNodeId;
@@ -210,6 +211,13 @@
                     !isIntfEnabled(osNode, osNode.vlanIntf())) {
                 addSystemInterface(osNode, INTEGRATION_BRIDGE, osNode.vlanIntf());
             }
+
+            osNode.phyIntfs().forEach(i -> {
+                if (!isIntfEnabled(osNode, i.intf())) {
+                    addSystemInterface(osNode, INTEGRATION_BRIDGE, i.intf());
+                }
+            });
+
         } catch (Exception e) {
             log.error("Exception occurred because of {}", e.toString());
         }
@@ -384,6 +392,13 @@
                         !isIntfEnabled(osNode, osNode.uplinkPort())) {
                     return false;
                 }
+
+                for (OpenstackPhyInterface intf : osNode.phyIntfs()) {
+                    if (intf != null && !isIntfEnabled(osNode, intf.intf())) {
+                        return false;
+                    }
+                }
+
                 return true;
             case COMPLETE:
             case INCOMPLETE:
@@ -508,7 +523,8 @@
                         if (osNode.state() == DEVICE_CREATED && (
                                 Objects.equals(portName, DEFAULT_TUNNEL) ||
                                 Objects.equals(portName, osNode.vlanIntf()) ||
-                                Objects.equals(portName, osNode.uplinkPort()))) {
+                                Objects.equals(portName, osNode.uplinkPort()) ||
+                                        containsPhyIntf(osNode, portName))) {
                             log.debug("Interface {} added to {}", portName, event.subject().id());
                             bootstrapNode(osNode);
                         }
@@ -521,7 +537,8 @@
                         if (osNode.state() == COMPLETE && (
                                 Objects.equals(portName, DEFAULT_TUNNEL) ||
                                 Objects.equals(portName, osNode.vlanIntf()) ||
-                                        Objects.equals(portName, osNode.uplinkPort()))) {
+                                        Objects.equals(portName, osNode.uplinkPort()) ||
+                                        containsPhyIntf(osNode, portName))) {
                             log.warn("Interface {} removed from {}", portName, event.subject().id());
                             setState(osNode, INCOMPLETE);
                         }
@@ -537,6 +554,24 @@
     }
 
     /**
+     * Checks whether the openstack node contains the given physical interface.
+     *
+     * @param osNode openstack node
+     * @param portName physical interface
+     * @return true if openstack node contains the given physical interface,
+     *          false otherwise
+     */
+    private boolean containsPhyIntf(OpenstackNode osNode, String portName) {
+        for (OpenstackPhyInterface phyIntf : osNode.phyIntfs()) {
+            if (Objects.equals(portName, phyIntf.intf())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * An internal openstack node listener.
      * The notification is triggered by OpenstackNodeStore.
      */