Fixes a bridge and ovsdb connection is removed in case openstack node is removed.

Change-Id: Ib84a76f91c86c24a192ec4cfe64c1f37b84cc6b2
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
index 2463e26..c54a136 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
@@ -27,6 +27,7 @@
 import java.util.Comparator;
 import java.util.List;
 
+import static org.onosproject.openstacknode.util.OpenstackNodeUtil.getGwByComputeNode;
 import static org.onosproject.openstacknode.util.OpenstackNodeUtil.prettyJson;
 
 /**
@@ -36,7 +37,7 @@
         description = "Lists all nodes registered in OpenStack node service")
 public class OpenstackNodeListCommand extends AbstractShellCommand {
 
-    private static final String FORMAT = "%-20s%-15s%-24s%-24s%-20s%-20s%-15s%s";
+    private static final String FORMAT = "%-20s%-15s%-24s%-24s%-20s%-20s%-15s%-15s%-15s";
 
     @Override
     protected void execute() {
@@ -48,7 +49,7 @@
             print("%s", json(osNodes));
         } else {
             print(FORMAT, "Hostname", "Type", "Integration Bridge",
-                    "Management IP", "Data IP", "VLAN Intf", "Uplink Port", "State");
+                    "Management IP", "Data IP", "VLAN Intf", "Uplink Port", "State", "SelectedGw");
             for (OpenstackNode osNode : osNodes) {
                 print(FORMAT,
                         osNode.hostname(),
@@ -58,7 +59,8 @@
                         osNode.dataIp() != null ? osNode.dataIp() : "",
                         osNode.vlanIntf() != null ? osNode.vlanIntf() : "",
                         osNode.uplinkPort() != null ? osNode.uplinkPort() : "",
-                        osNode.state());
+                        osNode.state(),
+                        getGwByComputeNode(osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY), osNode));
             }
             print("Total %s nodes", osNodeService.nodes().size());
         }
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 924cb7c..54a0c19 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
@@ -547,6 +547,12 @@
     }
 
     private void processOpenstackNodeRemoved(OpenstackNode osNode) {
+        OvsdbClientService client = getOvsdbClient(osNode, ovsdbPort, ovsdbController);
+        if (client == null) {
+            log.info("Failed to get ovsdb client");
+            return;
+        }
+
         //delete physical interfaces from the node
         removePhysicalInterface(osNode);
 
@@ -561,6 +567,17 @@
                 }
             });
         }
+
+        //delete tunnel bridge from the node
+        if (hasDpdkTunnelBridge(osNode)) {
+            client.dropBridge(TUNNEL_BRIDGE);
+        }
+
+        //delete integration bridge from the node
+        client.dropBridge(INTEGRATION_BRIDGE);
+
+        //disconnect ovsdb
+        client.disconnect();
     }
 
     /**
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java
index f19b8d5..b520b17 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java
@@ -48,7 +48,11 @@
 import java.io.IOException;
 import java.security.cert.X509Certificate;
 import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 
 import static org.onlab.util.Tools.get;
 
@@ -69,6 +73,7 @@
     private static final String ZERO = "0";
 
     private static final String DPDK_DEVARGS = "dpdk-devargs";
+    private static final String NOT_AVAILABLE = "N/A";
 
     /**
      * Prevents object installation from external.
@@ -290,6 +295,56 @@
     }
 
     /**
+     * Obtains the gateway node by openstack node. Note that the gateway
+     * node is determined by device's device identifier.
+     *
+     * @param gws                a collection of gateway nodes
+     * @param openstackNode      device identifier
+     * @return the hostname of selected gateway node
+     */
+    public static String getGwByComputeNode(Set<OpenstackNode> gws, OpenstackNode openstackNode) {
+        int numOfGw = gws.size();
+
+        if (numOfGw == 0) {
+            return NOT_AVAILABLE;
+        }
+
+        if (!openstackNode.type().equals(OpenstackNode.NodeType.COMPUTE)) {
+            return NOT_AVAILABLE;
+        }
+
+        int gwIndex = Math.abs(openstackNode.intgBridge().hashCode()) % numOfGw;
+
+        return getGwByIndex(gws, gwIndex).hostname();
+    }
+
+    /**
+     * Obtains gateway instance by giving index number.
+     *
+     * @param gws       a collection of gateway nodes
+     * @param index     index number
+     * @return gateway instance
+     */
+    private static OpenstackNode getGwByIndex(Set<OpenstackNode> gws, int index) {
+        Map<String, OpenstackNode> hashMap = new HashMap<>();
+        gws.forEach(gw -> hashMap.put(gw.hostname(), gw));
+        TreeMap<String, OpenstackNode> treeMap = new TreeMap<>(hashMap);
+        Iterator<String> iteratorKey = treeMap.keySet().iterator();
+
+        int intIndex = 0;
+        OpenstackNode gw = null;
+        while (iteratorKey.hasNext()) {
+            String key = iteratorKey.next();
+
+            if (intIndex == index) {
+                gw = treeMap.get(key);
+            }
+            intIndex++;
+        }
+        return gw;
+    }
+
+    /**
      * Builds up and a complete endpoint URL from gateway node.
      *
      * @param node gateway node