Supports netdev data path type in OpenstackNode.

Change-Id: I716276a98bd141e87bf20dd5314e52128cf7e495
diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
index 78e261f..2a47153 100644
--- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
+++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
@@ -58,6 +58,7 @@
     private final OpenstackAuth auth;
     private final String endPoint;
     private final OpenstackSshAuth sshAuth;
+    private final DatapathType datapathType;
 
     private static final String NOT_NULL_MSG = "Node % cannot be null";
 
@@ -79,6 +80,7 @@
      * @param auth          keystone authentication info
      * @param endPoint      openstack endpoint URL
      * @param sshAuth       ssh authentication info
+     * @param datapathType  data path type
      */
     protected DefaultOpenstackNode(String hostname, NodeType type,
                                    DeviceId intgBridge,
@@ -91,7 +93,8 @@
                                    Collection<ControllerInfo> controllers,
                                    OpenstackAuth auth,
                                    String endPoint,
-                                   OpenstackSshAuth sshAuth) {
+                                   OpenstackSshAuth sshAuth,
+                                   DatapathType datapathType) {
         this.hostname = hostname;
         this.type = type;
         this.intgBridge = intgBridge;
@@ -105,6 +108,7 @@
         this.auth = auth;
         this.endPoint = endPoint;
         this.sshAuth = sshAuth;
+        this.datapathType = datapathType;
     }
 
     @Override
@@ -148,6 +152,11 @@
     }
 
     @Override
+    public DatapathType datapathType() {
+        return datapathType;
+    }
+
+    @Override
     public NodeState state() {
         return state;
     }
@@ -247,7 +256,8 @@
                     Objects.equals(controllers, that.controllers) &&
                     Objects.equals(auth, that.auth) &&
                     Objects.equals(endPoint, that.endPoint) &&
-                    Objects.equals(sshAuth, that.sshAuth);
+                    Objects.equals(sshAuth, that.sshAuth) &&
+                    Objects.equals(datapathType, that.datapathType);
         }
         return false;
     }
@@ -265,7 +275,8 @@
                 controllers,
                 auth,
                 endPoint,
-                sshAuth);
+                sshAuth,
+                datapathType);
     }
 
     @Override
@@ -284,6 +295,7 @@
                 .add("auth", auth)
                 .add("endpoint", endPoint)
                 .add("sshAuth", sshAuth)
+                .add("datapathType", datapathType)
                 .toString();
     }
 
@@ -303,6 +315,7 @@
                 .authentication(auth)
                 .endPoint(endPoint)
                 .sshAuthInfo(sshAuth)
+                .datapathType(datapathType)
                 .build();
     }
 
@@ -389,7 +402,8 @@
                 .controllers(osNode.controllers())
                 .authentication(osNode.authentication())
                 .endPoint(osNode.endPoint())
-                .sshAuthInfo(osNode.sshAuthInfo());
+                .sshAuthInfo(osNode.sshAuthInfo())
+                .datapathType(osNode.datapathType());
     }
 
     /**
@@ -410,6 +424,7 @@
         private OpenstackAuth auth;
         private String endPoint;
         private OpenstackSshAuth sshAuth;
+        private DatapathType datapathType = DatapathType.NORMAL;
 
         // private constructor not intended to use from external
         private Builder() {
@@ -448,7 +463,8 @@
                     controllers,
                     auth,
                     endPoint,
-                    sshAuth);
+                    sshAuth,
+                    datapathType);
         }
 
         @Override
@@ -530,6 +546,12 @@
             this.sshAuth = sshAuth;
             return this;
         }
+
+        @Override
+        public Builder datapathType(DatapathType datapathType) {
+            this.datapathType = datapathType;
+            return this;
+        }
     }
 }
 
diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
index 5789deb..7f53ff4 100644
--- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
+++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
@@ -50,6 +50,14 @@
     }
 
     /**
+     * List of valid data path types.
+     */
+    enum DatapathType {
+        NORMAL,
+        NETDEV
+    }
+
+    /**
      * Returns hostname of the node.
      *
      * @return hostname
@@ -157,6 +165,13 @@
     String uplinkPort();
 
     /**
+     * Returns the data path type.
+     *
+     * @return data path type; normal or netdev
+     */
+    DatapathType datapathType();
+
+    /**
      * Returns the uplink port number.
      *
      * @return uplink port number
@@ -329,6 +344,14 @@
          * @return openstack node builder
          */
         Builder sshAuthInfo(OpenstackSshAuth sshAuth);
+
+        /**
+         * Returns openstack node builder with supplied data path type.
+         *
+         * @param datapathType data path type
+         * @return openstack node builder
+         */
+        Builder datapathType(DatapathType datapathType);
     }
 }
 
diff --git a/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java b/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
index 98a34a3..097a69c 100644
--- a/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
+++ b/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
@@ -105,6 +105,11 @@
     }
 
     @Override
+    public DatapathType datapathType() {
+        return DatapathType.NORMAL;
+    }
+
+    @Override
     public PortNumber uplinkPortNum() {
         return null;
     }
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/codec/OpenstackNodeCodec.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/codec/OpenstackNodeCodec.java
index a94aa10..e9f8e35 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/codec/OpenstackNodeCodec.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/codec/OpenstackNodeCodec.java
@@ -61,8 +61,10 @@
     private static final String AUTHENTICATION = "authentication";
     private static final String END_POINT = "endPoint";
     private static final String SSH_AUTH = "sshAuth";
+    private static final String DATA_PATH_TYPE = "datapathType";
 
     private static final String MISSING_MESSAGE = " is required in OpenstackNode";
+    private static final String UNSUPPORTED_DATAPATH_TYPE = "Unsupported datapath type";
 
     @Override
     public ObjectNode encode(OpenstackNode node, CodecContext context) {
@@ -72,7 +74,8 @@
                 .put(HOST_NAME, node.hostname())
                 .put(TYPE, node.type().name())
                 .put(STATE, node.state().name())
-                .put(MANAGEMENT_IP, node.managementIp().toString());
+                .put(MANAGEMENT_IP, node.managementIp().toString())
+                .put(DATA_PATH_TYPE, node.datapathType().name());
 
         OpenstackNode.NodeType type = node.type();
 
@@ -164,6 +167,17 @@
             nodeBuilder.dataIp(IpAddress.valueOf(json.get(DATA_IP).asText()));
         }
 
+        JsonNode datapathTypeJson = json.get(DATA_PATH_TYPE);
+
+        if (datapathTypeJson == null ||
+                datapathTypeJson.asText().equals(OpenstackNode.DatapathType.NORMAL.name().toLowerCase())) {
+            nodeBuilder.datapathType(OpenstackNode.DatapathType.NORMAL);
+        } else if (datapathTypeJson.asText().equals(OpenstackNode.DatapathType.NETDEV.name().toLowerCase())) {
+            nodeBuilder.datapathType(OpenstackNode.DatapathType.NETDEV);
+        } else {
+            throw new IllegalArgumentException(UNSUPPORTED_DATAPATH_TYPE + datapathTypeJson.asText());
+        }
+
         // parse physical interfaces
         List<OpenstackPhyInterface> phyIntfs = new ArrayList<>();
         JsonNode phyIntfsJson = json.get(PHYSICAL_INTERFACES);
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 06b65a3..07d71de 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
@@ -82,6 +82,7 @@
 import static org.onosproject.openstacknode.api.NodeState.DEVICE_CREATED;
 import static org.onosproject.openstacknode.api.NodeState.INCOMPLETE;
 import static org.onosproject.openstacknode.api.NodeState.INIT;
+import static org.onosproject.openstacknode.api.OpenstackNode.DatapathType.NETDEV;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
 import static org.onosproject.openstacknode.api.OpenstackNodeService.APP_ID;
@@ -272,16 +273,19 @@
 
         String dpid = deviceId.toString().substring(DPID_BEGIN);
 
-        BridgeDescription bridgeDesc = DefaultBridgeDescription.builder()
+        BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
                 .name(bridgeName)
                 .failMode(BridgeDescription.FailMode.SECURE)
                 .datapathId(dpid)
                 .disableInBand()
-                .controllers(controllers)
-                .build();
+                .controllers(controllers);
+
+        if (osNode.datapathType().equals(NETDEV)) {
+            builder.datapathType(osNode.datapathType().name().toLowerCase());
+        }
 
         BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
-        bridgeConfig.addBridge(bridgeDesc);
+        bridgeConfig.addBridge(builder.build());
     }
 
     /**
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java
index 106e4ea..f30611b 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DistributedOpenstackNodeStore.java
@@ -83,6 +83,7 @@
             .register(DefaultOpenstackNode.class)
             .register(OpenstackNode.NodeType.class)
             .register(NodeState.class)
+            .register(OpenstackNode.DatapathType.class)
             .register(OpenstackPhyInterface.class)
             .register(DefaultOpenstackPhyInterface.class)
             .register(ControllerInfo.class)
diff --git a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeCodecTest.java b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeCodecTest.java
index 77759c3..3d45238 100644
--- a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeCodecTest.java
+++ b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeCodecTest.java
@@ -149,6 +149,7 @@
         assertThat(node.controllers().size(), is(2));
         assertThat(node.sshAuthInfo().id(), is("sdn"));
         assertThat(node.sshAuthInfo().password(), is("sdn"));
+        assertThat(node.datapathType(), is(OpenstackNode.DatapathType.NORMAL));
 
         node.phyIntfs().forEach(intf -> {
             if (intf.network().equals("mgmtnetwork")) {
@@ -167,6 +168,10 @@
                 assertThat(ctrl.port(), is(6663));
             }
         });
+
+        OpenstackNode dpdkNode = getOpenstackNode("OpenstackDpdkComputeNode.json");
+
+        assertThat(dpdkNode.datapathType(), is(OpenstackNode.DatapathType.NETDEV));
     }
 
     /**
diff --git a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeJsonMatcher.java b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeJsonMatcher.java
index e8b6d07..3614f5f 100644
--- a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeJsonMatcher.java
+++ b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/codec/OpenstackNodeJsonMatcher.java
@@ -42,6 +42,7 @@
     private static final String AUTHENTICATION = "authentication";
     private static final String END_POINT = "endPoint";
     private static final String SSH_AUTH = "sshAuth";
+    private static final String DATA_PATH_TYPE = "datapathType";
 
     private OpenstackNodeJsonMatcher(OpenstackNode node) {
         this.node = node;
@@ -143,6 +144,16 @@
             }
         }
 
+        // check datapath type
+        JsonNode jsonDatapathType = jsonNode.get(DATA_PATH_TYPE);
+        if (jsonDatapathType != null) {
+            OpenstackNode.DatapathType datapathType = node.datapathType();
+            if (!OpenstackNode.DatapathType.valueOf(jsonDatapathType.asText()).equals(datapathType)) {
+                description.appendText("datapathType was " + jsonDatapathType);
+                return false;
+            }
+        }
+
         // check physical interfaces
         JsonNode jsonPhyIntfs = jsonNode.get(PHYSICAL_INTERFACES);
         if (jsonPhyIntfs != null) {
diff --git a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java
index ee5e478..e24b4e4 100644
--- a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java
+++ b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java
@@ -423,7 +423,8 @@
                 intgBridge.id(),
                 ipAddr,
                 ipAddr,
-                null, null, state, phyIntfs, controllers, null, null, null);
+                null, null, state, phyIntfs, controllers,
+                null, null, null, OpenstackNode.DatapathType.NORMAL);
     }
 
     private static OpenstackNode createGatewayNode(String hostname,
@@ -438,8 +439,8 @@
                 intgBridge.id(),
                 ipAddr,
                 ipAddr,
-                null, uplinkPort, state,
-                null, null, null, null, null);
+                null, uplinkPort, state, null, null, null, null, null,
+                OpenstackNode.DatapathType.NORMAL);
     }
 
     private static final class TestDevice extends DefaultDevice {
@@ -501,7 +502,8 @@
                                   Set<ControllerInfo> controllers,
                                   OpenstackAuth auth,
                                   String endPoint,
-                                  OpenstackSshAuth sshAuth) {
+                                  OpenstackSshAuth sshAuth,
+                                  DatapathType datapathType) {
             super(hostname,
                     type,
                     intgBridge,
@@ -514,7 +516,8 @@
                     controllers,
                     auth,
                     endPoint,
-                    sshAuth);
+                    sshAuth,
+                    datapathType);
         }
 
         @Override
diff --git a/apps/openstacknode/app/src/test/resources/org/onosproject/openstacknode/codec/OpenstackDpdkComputeNode.json b/apps/openstacknode/app/src/test/resources/org/onosproject/openstacknode/codec/OpenstackDpdkComputeNode.json
new file mode 100644
index 0000000..2313047
--- /dev/null
+++ b/apps/openstacknode/app/src/test/resources/org/onosproject/openstacknode/codec/OpenstackDpdkComputeNode.json
@@ -0,0 +1,33 @@
+{
+  "hostname": "compute-01",
+  "type": "COMPUTE",
+  "managementIp": "172.16.130.4",
+  "dataIp": "172.16.130.4",
+  "vlanPort": "eth2",
+  "integrationBridge": "of:00000000000000a1",
+  "datapathType" : "netdev",
+  "phyIntfs": [
+    {
+      "network": "mgmtnetwork",
+      "intf": "eth3"
+    },
+    {
+      "network": "oamnetwork",
+      "intf": "eth4"
+    }
+  ],
+  "sshAuth": {
+    "id": "sdn",
+    "password": "sdn"
+  },
+  "controllers": [
+    {
+      "ip": "10.10.10.2",
+      "port": 6653
+    },
+    {
+      "ip": "10.10.10.3",
+      "port": 6663
+    }
+  ]
+}
\ No newline at end of file
diff --git a/apps/openstacknode/network-cfg.json b/apps/openstacknode/network-cfg.json
index 76c5c09..6de0cf3 100644
--- a/apps/openstacknode/network-cfg.json
+++ b/apps/openstacknode/network-cfg.json
@@ -20,6 +20,11 @@
                 "intf": "eth4"
               }
             ],
+            "sshAuth" : {
+              "id": "id",
+              "password" : "password"
+            },
+            "datapathType" : "netdev",
             "controllers": [
               {
                 "ip": "10.10.10.2",