Support GATEWAY type node bootstrapping

- Create router bridge and pactch port to integration bridge for gateway node
- Refactored to listen map event for node add/update
- Added CLIs

Change-Id: Id653f2a2c01d94036f77e6ce1b1230111f3dbbb1
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
new file mode 100644
index 0000000..d5cb8ed
--- /dev/null
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.openstacknode.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.Device;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.openstacknode.OpenstackNode;
+import org.onosproject.openstacknode.OpenstackNodeService;
+
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+import static org.onosproject.openstacknode.Constants.*;
+import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
+
+/**
+ * Checks detailed node init state.
+ */
+@Command(scope = "onos", name = "openstack-node-check",
+        description = "Shows detailed node init state")
+public class OpenstackNodeCheckCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "hostname", description = "Hostname",
+            required = true, multiValued = false)
+    private String hostname = null;
+
+    private static final String MSG_OK = "OK";
+    private static final String MSG_NO = "NO";
+
+    @Override
+    protected void execute() {
+        OpenstackNodeService nodeService = AbstractShellCommand.get(OpenstackNodeService.class);
+        DeviceService deviceService = AbstractShellCommand.get(DeviceService.class);
+
+        OpenstackNode node = nodeService.nodes()
+                .stream()
+                .filter(n -> n.hostname().equals(hostname))
+                .findFirst()
+                .orElse(null);
+
+        if (node == null) {
+            print("Cannot find %s from registered nodes", hostname);
+            return;
+        }
+
+        print("%n[Integration Bridge Status]");
+        Device device = deviceService.getDevice(node.intBridge());
+        if (device != null) {
+            print("%s %s=%s available=%s %s",
+                    deviceService.isAvailable(device.id()) ? MSG_OK : MSG_NO,
+                    INTEGRATION_BRIDGE,
+                    device.id(),
+                    deviceService.isAvailable(device.id()),
+                    device.annotations());
+
+            print(getPortState(deviceService, node.intBridge(), DEFAULT_TUNNEL));
+        } else {
+            print("%s %s=%s is not available",
+                    MSG_NO,
+                    INTEGRATION_BRIDGE,
+                    node.intBridge());
+        }
+
+        if (node.type().equals(GATEWAY)) {
+            print("%n[Router Bridge Status]");
+            device = deviceService.getDevice(node.routerBridge().get());
+            if (device != null) {
+                print("%s %s=%s available=%s %s",
+                        deviceService.isAvailable(device.id()) ? MSG_OK : MSG_NO,
+                        ROUTER_BRIDGE,
+                        device.id(),
+                        deviceService.isAvailable(device.id()),
+                        device.annotations());
+
+                print(getPortState(deviceService, node.routerBridge().get(), PATCH_ROUT_BRIDGE));
+                print(getPortState(deviceService, node.intBridge(), PATCH_INTG_BRIDGE));
+            } else {
+                print("%s %s=%s is not available",
+                        MSG_NO,
+                        ROUTER_BRIDGE,
+                        node.intBridge());
+            }
+        }
+    }
+
+    private String getPortState(DeviceService deviceService, DeviceId deviceId, String portName) {
+        Port port = deviceService.getPorts(deviceId).stream()
+                .filter(p -> p.annotations().value(PORT_NAME).equals(portName) &&
+                        p.isEnabled())
+                .findAny().orElse(null);
+
+        if (port != null) {
+            return String.format("%s %s portNum=%s enabled=%s %s",
+                    port.isEnabled() ? MSG_OK : MSG_NO,
+                    portName,
+                    port.number(),
+                    port.isEnabled() ? Boolean.TRUE : Boolean.FALSE,
+                    port.annotations());
+        } else {
+            return String.format("%s %s does not exist", MSG_NO, portName);
+        }
+    }
+}
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeInitCommand.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeInitCommand.java
new file mode 100644
index 0000000..8f4dbb1
--- /dev/null
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeInitCommand.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.openstacknode.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.openstacknode.OpenstackNode;
+import org.onosproject.openstacknode.OpenstackNodeService;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Initializes nodes for OpenStack node service.
+ */
+@Command(scope = "onos", name = "openstack-node-init",
+        description = "Initializes nodes for OpenStack node service")
+public class OpenstackNodeInitCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "hostnames", description = "Hostname(s)",
+            required = true, multiValued = true)
+    private String[] hostnames = null;
+
+    @Override
+    protected void execute() {
+        OpenstackNodeService nodeService = AbstractShellCommand.get(OpenstackNodeService.class);
+
+        for (String hostname : hostnames) {
+            OpenstackNode node;
+            try {
+                node = nodeService.nodes()
+                        .stream()
+                        .filter(n -> n.hostname().equals(hostname))
+                        .findFirst().get();
+            } catch (NoSuchElementException e) {
+                print("Unable to find %s", hostname);
+                continue;
+            }
+
+            nodeService.addOrUpdateNode(node);
+        }
+    }
+}
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
new file mode 100644
index 0000000..bfb1070
--- /dev/null
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.openstacknode.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.openstacknode.OpenstackNode;
+import org.onosproject.openstacknode.OpenstackNodeService;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all nodes registered to the service.
+ */
+@Command(scope = "onos", name = "openstack-nodes",
+        description = "Lists all nodes registered in OpenStack node service")
+public class OpenstackNodeListCommand extends AbstractShellCommand {
+
+    private static final String COMPLETE = "COMPLETE";
+    private static final String INCOMPLETE = "INCOMPLETE";
+
+    @Override
+    protected void execute() {
+        OpenstackNodeService nodeService = AbstractShellCommand.get(OpenstackNodeService.class);
+        List<OpenstackNode> nodes = nodeService.nodes();
+        Collections.sort(nodes, OpenstackNode.OPENSTACK_NODE_COMPARATOR);
+
+        if (outputJson()) {
+            print("%s", json(nodeService, nodes));
+        } else {
+            for (OpenstackNode node : nodes) {
+                print("hostname=%s, type=%s, managementIp=%s, dataIp=%s, intBridge=%s, routerBridge=%s init=%s",
+                        node.hostname(),
+                        node.type(),
+                        node.managementIp(),
+                        node.dataIp(),
+                        node.intBridge(),
+                        node.routerBridge(),
+                        getState(nodeService, node));
+            }
+            print("Total %s nodes", nodeService.nodes().size());
+        }
+    }
+
+    private JsonNode json(OpenstackNodeService nodeService, List<OpenstackNode> nodes) {
+        ObjectMapper mapper = new ObjectMapper();
+        ArrayNode result = mapper.createArrayNode();
+        for (OpenstackNode node : nodes) {
+            result.add(mapper.createObjectNode()
+                    .put("hostname", node.hostname())
+                    .put("type", node.type().name())
+                    .put("managementIp", node.managementIp().toString())
+                    .put("dataIp", node.dataIp().toString())
+                    .put("intBridge", node.intBridge().toString())
+                    .put("routerBridge", node.routerBridge().toString())
+                    .put("state", getState(nodeService, node)));
+        }
+        return result;
+    }
+
+    private String getState(OpenstackNodeService nodeService, OpenstackNode node) {
+        return nodeService.isComplete(node.hostname()) ? COMPLETE : INCOMPLETE;
+    }
+}
\ No newline at end of file
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/package-info.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/package-info.java
new file mode 100644
index 0000000..6a6e636
--- /dev/null
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Console commands to manage OpenStack nodes.
+ */
+package org.onosproject.openstacknode.cli;
\ No newline at end of file