Allow to inject external_id field when creating an OVSDB interface

Change-Id: Iabc69771ac5dd1a321f8c9cc440fa2e166965a17
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbInterface.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbInterface.java
index b194695..9a60372 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbInterface.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbInterface.java
@@ -15,18 +15,21 @@
  */
 package org.onosproject.ovsdb.controller;
 
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.ovsdb.controller.OvsdbConstant.*;
+import com.google.common.collect.Maps;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.behaviour.PatchDescription;
+import org.onosproject.net.behaviour.TunnelDescription;
+import org.onosproject.ovsdb.rfc.table.Interface.InterfaceColumn;
 
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
-import com.google.common.collect.Maps;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.behaviour.PatchDescription;
-import org.onosproject.net.behaviour.TunnelDescription;
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onosproject.ovsdb.controller.OvsdbConstant.PATCH_PEER;
+import static org.onosproject.ovsdb.controller.OvsdbConstant.TUNNEL_KEY;
+import static org.onosproject.ovsdb.controller.OvsdbConstant.TUNNEL_LOCAL_IP;
+import static org.onosproject.ovsdb.controller.OvsdbConstant.TUNNEL_REMOTE_IP;
 
 /**
  * The class representing an OVSDB interface.
@@ -72,17 +75,21 @@
     private final String name;
     private final Type type;
     private final Optional<Long> mtu;
+    private final Map<InterfaceColumn, Map<String, String>> data;
 
     /* Adds more configs */
 
     /* Fields start with "options:" prefix defined in the OVSDB */
     private final Map<String, String> options;
 
-    private OvsdbInterface(String name, Type type, Optional<Long> mtu, Map<String, String> options) {
+    private OvsdbInterface(String name, Type type, Optional<Long> mtu,
+                           Map<String, String> options, Map<InterfaceColumn,
+                            Map<String, String>> data) {
         this.name = name;
-        this.type = checkNotNull(type, "the type of interface can not be null");
+        this.type = type;
         this.mtu = mtu;
         this.options = Maps.newHashMap(options);
+        this.data = data;
     }
 
     /**
@@ -130,6 +137,15 @@
         return options;
     }
 
+    /**
+     * Returns the data of the interface.
+     *
+     * @return interface data
+     */
+    public Map<InterfaceColumn, Map<String, String>> data() {
+        return data;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(name);
@@ -154,6 +170,7 @@
                 .add("type", type)
                 .add("mtu", mtu)
                 .add("options", options)
+                .add("data", data)
                 .toString();
     }
 
@@ -194,6 +211,7 @@
         private Type type;
         private Optional<Long> mtu = Optional.empty();
         private Map<String, String> options = Maps.newHashMap();
+        private Map<InterfaceColumn, Map<String, String>> data = Maps.newHashMap();
 
         private Builder() {
         }
@@ -243,7 +261,7 @@
          * @return ovsdb interface
          */
         public OvsdbInterface build() {
-            return new OvsdbInterface(name, type, mtu, options);
+            return new OvsdbInterface(name, type, mtu, options, data);
         }
 
         /**
@@ -289,5 +307,16 @@
             this.options = Maps.newHashMap(options);
             return this;
         }
+
+        /**
+         * Returns OVSDB interface builder with given data.
+         *
+         * @param data map of data
+         * @return ovsdb interface builder
+         */
+        public Builder data(Map<InterfaceColumn, Map<String, String>> data) {
+            this.data = data;
+            return this;
+        }
     }
 }
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index 16311dc..ccb153d 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -1096,7 +1096,6 @@
 
         if (getPortUuid(ovsdbIface.name(), bridgeUuid) != null) {
             log.warn("Interface {} already exists", ovsdbIface.name());
-            // remove existing one and re-create?
             return false;
         }
 
@@ -1117,11 +1116,12 @@
         List<Mutation> mutations = Lists.newArrayList(mutation);
         operations.add(new Mutate(dbSchema.getTableSchema(BRIDGE), conditions, mutations));
 
-        // insert an interface
         Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
         intf.setName(ovsdbIface.name());
 
-        intf.setType(ovsdbIface.typeToString());
+        if (ovsdbIface.type() != null) {
+            intf.setType(ovsdbIface.typeToString());
+        }
 
         if (ovsdbIface.mtu().isPresent()) {
             Set<Long> mtuSet = Sets.newConcurrentHashSet();
@@ -1131,6 +1131,13 @@
         }
 
         intf.setOptions(ovsdbIface.options());
+
+        ovsdbIface.data().forEach((k, v) -> {
+            if (k == Interface.InterfaceColumn.EXTERNALIDS) {
+                intf.setExternalIds(v);
+            }
+        });
+
         Insert intfInsert = new Insert(dbSchema.getTableSchema(INTERFACE), INTERFACE, intf.getRow());
         operations.add(intfInsert);