CORD-208 Implement additional ovsdb client methods

- Create a bridge with data path id
- Create a tunnel port with some options

Change-Id: I9fbf6322272f9151c0fc904d1c681e5ffb793be0
diff --git a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
index 86f6226..e619f8e 100644
--- a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
+++ b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
@@ -28,6 +28,7 @@
 import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -50,6 +51,17 @@
     void createTunnel(IpAddress srcIp, IpAddress dstIp);
 
     /**
+     * Creates a tunnel port with given options.
+     *
+     * @param bridgeName bridge name
+     * @param portName port name
+     * @param tunnelType tunnel type
+     * @param options tunnel options
+     * @return true if tunnel creation is successful, false otherwise
+     */
+    boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options);
+
+    /**
      * Drops the configuration for the tunnel.
      *
      * @param srcIp source IP address
@@ -72,6 +84,17 @@
     void createBridge(String bridgeName);
 
     /**
+     * Creates a bridge with given name and dpid.
+     * Sets the bridge's controller with given controllers.
+     *
+     * @param bridgeName bridge name
+     * @param dpid data path id
+     * @param controllers controllers
+     * @return true if bridge creation is successful, false otherwise
+     */
+    boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers);
+
+    /**
      * Drops a bridge.
      *
      * @param bridgeName bridge name
diff --git a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index 3a84d00..2575a25 100644
--- a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -73,6 +73,8 @@
 
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -481,6 +483,52 @@
         log.info("Create bridge success");
     }
 
+    @Override
+    public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) {
+
+        DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
+        String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
+
+        if (dbSchema == null || ovsUuid == null) {
+            log.warn("Couldn't find database Open_vSwitch");
+            return false;
+        }
+
+        String bridgeUuid = getBridgeUuid(bridgeName);
+        if (bridgeUuid != null) {
+            log.warn("Bridge {} is already exist", bridgeName);
+            // remove existing one and re-create?
+            return false;
+        }
+
+        Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, OvsdbTable.BRIDGE);
+        bridge.setName(bridgeName);
+
+        Set<String> failMode = new HashSet<>(Arrays.asList("secure"));
+        bridge.setFailMode(failMode);
+
+        Set<String> protocols = new HashSet<>(Arrays.asList(OvsdbConstant.OPENFLOW13));
+        bridge.setProtocols(protocols);
+
+        Map<String, String> options = new HashMap<>();
+        options.put("datapath-id", dpid);
+        bridge.setOtherConfig(options);
+
+        bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
+                                  OvsdbConstant.DATABASENAME, "bridges",
+                                  ovsUuid, bridge.getRow());
+
+        if (bridgeUuid != null) {
+            createPort(bridgeName, bridgeName);
+        } else {
+            log.warn("Failed to create bridge {} on {}", bridgeName, nodeId.toString());
+            return false;
+        }
+
+        setControllersWithUUID(UUID.uuid(bridgeUuid), controllers);
+        return true;
+    }
+
     /**
      * Sets the bridge's controller automatically.
      * <p/>
@@ -648,6 +696,50 @@
     }
 
     @Override
+    public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) {
+
+        String bridgeUuid  = getBridgeUuid(bridgeName);
+        if (bridgeUuid == null) {
+            log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
+            return false;
+        }
+
+        if (getPortUuid(portName, bridgeUuid) != null) {
+            log.warn("Port {} already exists", portName);
+            // remove existing one and re-create?
+            return false;
+        }
+
+        ArrayList<Operation> operations = Lists.newArrayList();
+        DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
+
+        // insert a new port to the port table
+        Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
+        port.setName(portName);
+        Insert portInsert = new Insert(dbSchema.getTableSchema("Port"), "Port", port.getRow());
+        portInsert.getRow().put("interfaces", UUID.uuid("Interface"));
+        operations.add(portInsert);
+
+        // update the bridge table
+        Condition condition = ConditionUtil.equals("_uuid", UUID.uuid(bridgeUuid));
+        Mutation mutation = MutationUtil.insert("ports", UUID.uuid("Port"));
+        List<Condition> conditions = new ArrayList<>(Arrays.asList(condition));
+        List<Mutation> mutations = new ArrayList<>(Arrays.asList(mutation));
+        operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
+
+        // insert a tunnel interface
+        Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
+        intf.setName(portName);
+        intf.setType(tunnelType);
+        intf.setOptions(options);
+        Insert intfInsert = new Insert(dbSchema.getTableSchema("Interface"), "Interface", intf.getRow());
+        operations.add(intfInsert);
+
+        transactConfig(OvsdbConstant.DATABASENAME, operations);
+        return true;
+    }
+
+    @Override
     public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
         String bridgeName = OvsdbConstant.INTEGRATION_BRIDGE;
         String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
diff --git a/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java b/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
index 71fee4f..2c418d5 100644
--- a/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
+++ b/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
@@ -34,6 +34,7 @@
 import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -52,6 +53,11 @@
     }
 
     @Override
+    public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) {
+        return true;
+    }
+
+    @Override
     public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
 
     }
@@ -67,6 +73,11 @@
     }
 
     @Override
+    public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) {
+        return true;
+    }
+
+    @Override
     public void dropBridge(String bridgeName) {
 
     }