ONOS-4660 Additional GATEWAY type node bootstrap

- Add uplink interface to the router bridge
- Set separate controller for the router bridge
- Use OVSDB provider to check the ports list and keep OVSDB session

Limitation:
OVSDB provider does not provide port or bridge updates, that is,
any changes on the router bridge may not be detected by ONOS

Change-Id: I1f17f4fb2c050afdbda1e5ffc06f6485903d3d90
diff --git a/apps/openstacknode/network-cfg.json b/apps/openstacknode/network-cfg.json
index 4720104..daecd85 100644
--- a/apps/openstacknode/network-cfg.json
+++ b/apps/openstacknode/network-cfg.json
@@ -23,7 +23,9 @@
                         "managementIp" : "10.203.198.125",
                         "dataIp" : "10.134.33.208",
                         "integrationBridge" : "of:00000000000000a3",
-                        "routerBridge" : "of:00000000000000b1"
+                        "routerBridge" : "of:00000000000000b3",
+                        "uplinkPort" : "veth1",
+                        "routerController" : "172.17.0.2"
                     },
                     {
                         "hostname" : "gateway-02",
@@ -31,7 +33,9 @@
                         "managementIp" : "10.203.198.131",
                         "dataIp" : "10.134.33.209",
                         "integrationBridge" : "of:00000000000000a4",
-                        "routerBridge" : "of:00000000000000b2"
+                        "routerBridge" : "of:00000000000000b4",
+                        "uplinkPort" : "veth1",
+                        "routerController" : "172.17.0.2"
                     }
                 ]
             }
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java
index b4c3f04..b4074f7 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java
@@ -28,4 +28,8 @@
     public static final String DEFAULT_TUNNEL = "vxlan";
     public static final String PATCH_INTG_BRIDGE = "patch-intg";
     public static final String PATCH_ROUT_BRIDGE = "patch-rout";
+
+    public static final int DEFAULT_OVSDB_PORT = 6640;
+    public static final int DEFAULT_OFPORT = 6653;
+    public static final String DEFAULT_OF_PROTO = "tcp";
 }
\ No newline at end of file
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java
index 4508bdd..42edd72 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java
@@ -41,6 +41,9 @@
     private final IpAddress dataIp;
     private final DeviceId integrationBridge;
     private final Optional<DeviceId> routerBridge;
+    private final Optional<String> uplink;
+    // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
+    private final Optional<IpAddress> routerController;
     private final NodeState state;
 
     public static final Comparator<OpenstackNode> OPENSTACK_NODE_COMPARATOR =
@@ -52,6 +55,8 @@
                           IpAddress dataIp,
                           DeviceId integrationBridge,
                           Optional<DeviceId> routerBridge,
+                          Optional<String> uplink,
+                          Optional<IpAddress> routerController,
                           NodeState state) {
         this.hostname = hostname;
         this.type = type;
@@ -59,6 +64,8 @@
         this.dataIp = dataIp;
         this.integrationBridge = integrationBridge;
         this.routerBridge = routerBridge;
+        this.uplink = uplink;
+        this.routerController = routerController;
         this.state = state;
     }
 
@@ -76,6 +83,8 @@
                 node.dataIp,
                 node.integrationBridge,
                 node.routerBridge,
+                node.uplink,
+                node.routerController,
                 state);
     }
 
@@ -135,6 +144,27 @@
     }
 
     /**
+     * Returns the router bridge controller.
+     * It returns valid value only if the node type is GATEWAY.
+     *
+     * @return device id; or empty value
+     */
+    // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
+    public Optional<IpAddress> routerController() {
+        return routerController;
+    }
+
+    /**
+     * Returns the uplink interface name.
+     * It returns valid value only if the node type is GATEWAY.
+     *
+     * @return uplink interface name; or empty value
+     */
+    public Optional<String> uplink() {
+        return uplink;
+    }
+
+    /**
      * Returns the init state of the node.
      *
      * @return init state
@@ -165,7 +195,9 @@
                     Objects.equals(managementIp, that.managementIp) &&
                     Objects.equals(dataIp, that.dataIp) &&
                     Objects.equals(integrationBridge, that.integrationBridge) &&
-                    Objects.equals(routerBridge, that.routerBridge)) {
+                    Objects.equals(routerBridge, that.routerBridge) &&
+                    Objects.equals(uplink, that.uplink) &&
+                    Objects.equals(routerController, that.routerController)) {
                 return true;
             }
         }
@@ -179,7 +211,9 @@
                 managementIp,
                 dataIp,
                 integrationBridge,
-                routerBridge);
+                routerBridge,
+                uplink,
+                routerController);
     }
 
     @Override
@@ -191,6 +225,8 @@
                 .add("dataIp", dataIp)
                 .add("integrationBridge", integrationBridge)
                 .add("routerBridge", routerBridge)
+                .add("uplink", uplink)
+                .add("routerController", routerController)
                 .add("state", state)
                 .toString();
     }
@@ -214,6 +250,9 @@
         private IpAddress dataIp;
         private DeviceId integrationBridge;
         private Optional<DeviceId> routerBridge = Optional.empty();
+        private Optional<String> uplink = Optional.empty();
+        // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
+        private Optional<IpAddress> routerController = Optional.empty();
         private NodeState state = INIT;
 
         private Builder() {
@@ -226,12 +265,23 @@
             checkNotNull(dataIp);
             checkNotNull(integrationBridge);
             checkNotNull(routerBridge);
+            checkNotNull(uplink);
+            checkNotNull(routerController);
+
+            if (type == NodeType.GATEWAY) {
+                checkArgument(routerBridge.isPresent());
+                checkArgument(uplink.isPresent());
+                checkArgument(routerController.isPresent());
+            }
+
             return new OpenstackNode(hostname,
                     type,
                     managementIp,
                     dataIp,
                     integrationBridge,
                     routerBridge,
+                    uplink,
+                    routerController,
                     state);
         }
 
@@ -302,6 +352,29 @@
         }
 
         /**
+         * Returns node builder with the uplink interface name.
+         *
+         * @param uplink uplink interface name
+         * @return openstack node builder
+         */
+        public Builder uplink(String uplink) {
+            this.uplink = Optional.ofNullable(uplink);
+            return this;
+        }
+
+        /**
+         * Returns node builder with the router controller.
+         *
+         * @param routerController router contoller
+         * @return openstack node builder
+         */
+        // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
+        public Builder routerController(IpAddress routerController) {
+            this.routerController = Optional.ofNullable(routerController);
+            return this;
+        }
+
+        /**
          * Returns node builder with the init state.
          *
          * @param state node init state
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java
index ea2d30d..c20e678 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java
@@ -40,7 +40,12 @@
     private static final String MANAGEMENT_IP = "managementIp";
     private static final String DATA_IP = "dataIp";
     private static final String INTEGRATION_BRIDGE = "integrationBridge";
+
+    // GATEWAY node specific fields
     private static final String ROUTER_BRIDGE = "routerBridge";
+    private static final String UPLINK_PORT_NAME = "uplinkPort";
+    // TODO remove this when vRouter supports multiple switches
+    private static final String ROUTER_CONTROLLER = "routerController";
 
     @Override
     public boolean isValid() {
@@ -59,7 +64,9 @@
                     MANAGEMENT_IP,
                     DATA_IP,
                     INTEGRATION_BRIDGE,
-                    ROUTER_BRIDGE
+                    ROUTER_BRIDGE,
+                    UPLINK_PORT_NAME,
+                    ROUTER_CONTROLLER
             );
 
             result &= isString(osNode, HOST_NAME, MANDATORY);
@@ -74,6 +81,8 @@
             if (osNode.get(TYPE).asText().equals(GATEWAY.name())) {
                 result &= isString(osNode, ROUTER_BRIDGE, MANDATORY);
                 DeviceId.deviceId(osNode.get(ROUTER_BRIDGE).asText());
+                result &= isString(osNode, UPLINK_PORT_NAME, MANDATORY);
+                result &= isIpAddress(osNode, ROUTER_CONTROLLER, MANDATORY);
             }
         }
         return result;
@@ -97,7 +106,9 @@
                     .hostname(get(node, HOST_NAME));
 
             if (type.equals(GATEWAY)) {
-                nodeBuilder.routerBridge(DeviceId.deviceId(get(node, ROUTER_BRIDGE)));
+                nodeBuilder.routerBridge(DeviceId.deviceId(get(node, ROUTER_BRIDGE)))
+                        .uplink(get(node, UPLINK_PORT_NAME))
+                        .routerController(IpAddress.valueOf(get(node, ROUTER_CONTROLLER)));
             }
             nodes.add(nodeBuilder.build());
         }
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
index 56c422c..fcfcaaa 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
@@ -30,6 +30,7 @@
 import org.onlab.util.Tools;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
 import org.onosproject.cluster.LeadershipService;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.core.ApplicationId;
@@ -41,6 +42,7 @@
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.behaviour.BridgeConfig;
 import org.onosproject.net.behaviour.BridgeDescription;
+import org.onosproject.net.behaviour.BridgeName;
 import org.onosproject.net.behaviour.ControllerInfo;
 import org.onosproject.net.behaviour.DefaultBridgeDescription;
 import org.onosproject.net.behaviour.DefaultPatchDescription;
@@ -72,6 +74,7 @@
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
@@ -89,7 +92,6 @@
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
 
-
 /**
  * Initializes devices in compute/gateway nodes according to there type.
  */
@@ -106,8 +108,6 @@
             .register(NodeState.class);
 
     private static final String OVSDB_PORT = "ovsdbPort";
-    private static final int DEFAULT_OVSDB_PORT = 6640;
-    private static final int DEFAULT_OFPORT = 6653;
     private static final int DPID_BEGIN = 3;
 
     private static final String APP_ID = "org.onosproject.openstacknode";
@@ -120,7 +120,7 @@
     protected DeviceService deviceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected OvsdbController controller;
+    protected OvsdbController ovsdbController;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ClusterService clusterService;
@@ -142,7 +142,7 @@
     private int ovsdbPort = DEFAULT_OVSDB_PORT;
 
     private final ExecutorService eventExecutor =
-            newSingleThreadScheduledExecutor(groupedThreads("onos/openstack-node", "event-handler"));
+            newSingleThreadScheduledExecutor(groupedThreads("onos/openstack-node", "event-handler", log));
 
     private final ConfigFactory configFactory =
             new ConfigFactory<ApplicationId, OpenstackNodeConfig>(
@@ -221,10 +221,6 @@
 
     @Override
     public void deleteNode(OpenstackNode node) {
-        if (isOvsdbConnected(node)) {
-            OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort);
-            controller.getOvsdbClient(ovsdb).disconnect();
-        }
         nodeStore.remove(node.hostname());
         process(new OpenstackNodeEvent(INCOMPLETE, node));
     }
@@ -236,15 +232,13 @@
             connectOvsdb(node);
             return;
         }
-
         process(new OpenstackNodeEvent(INIT, node));
-        createBridge(node, INTEGRATION_BRIDGE,
-                     node.intBridge().toString().substring(DPID_BEGIN));
 
-        // creates additional router bridge if the node type is GATEWAY
+        createBridge(node, INTEGRATION_BRIDGE, node.intBridge());
         if (node.type().equals(NodeType.GATEWAY)) {
-            createBridge(node, ROUTER_BRIDGE,
-                         node.routerBridge().get().toString().substring(DPID_BEGIN));
+            createBridge(node, ROUTER_BRIDGE, node.routerBridge().get());
+            // TODO remove this when OVSDB provides port event
+            setNodeState(node, nodeState(node));
         }
     }
 
@@ -256,20 +250,18 @@
             return;
         }
         process(new OpenstackNodeEvent(DEVICE_CREATED, node));
+
         createTunnelInterface(node);
-        // creates additional patch ports connecting integration bridge and
-        // router bridge if the node type is GATEWAY
         if (node.type().equals(NodeType.GATEWAY)) {
             createPatchInterface(node);
+            addUplink(node);
+            // TODO remove this when OVSDB provides port event
+            setNodeState(node, nodeState(node));
         }
     }
 
     @Override
     public void processCompleteState(OpenstackNode node) {
-        if (isOvsdbConnected(node)) {
-            OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort);
-            controller.getOvsdbClient(ovsdb).disconnect();
-        }
         process(new OpenstackNodeEvent(COMPLETE, node));
         log.info("Finished init {}", node.hostname());
     }
@@ -334,50 +326,84 @@
     }
 
     private void setNodeState(OpenstackNode node, NodeState newState) {
-        log.debug("Changed {} state: {}", node.hostname(), newState);
-        nodeStore.put(node.hostname(), OpenstackNode.getUpdatedNode(node, newState));
+        if (node.state() != newState) {
+            log.debug("Changed {} state: {}", node.hostname(), newState);
+            nodeStore.put(node.hostname(), OpenstackNode.getUpdatedNode(node, newState));
+        }
     }
 
     private NodeState nodeState(OpenstackNode node) {
-        if (!deviceService.isAvailable(node.intBridge())) {
+        if (!isOvsdbConnected(node) || !deviceService.isAvailable(node.intBridge())) {
             return INIT;
         }
+
+        // TODO use device service when we use single ONOS cluster for both openstackNode and vRouter
         if (node.type().equals(NodeType.GATEWAY) &&
-                !deviceService.isAvailable(node.routerBridge().get())) {
+                !isBridgeCreated(node.ovsdbId(), ROUTER_BRIDGE)) {
             return INIT;
         }
 
-        if (!isIfaceCreated(node.intBridge(), DEFAULT_TUNNEL)) {
-            return DEVICE_CREATED;
-        }
-        if (node.type().equals(NodeType.GATEWAY) && (
-                !isIfaceCreated(node.routerBridge().get(), PATCH_ROUT_BRIDGE) ||
-                !isIfaceCreated(node.intBridge(), PATCH_INTG_BRIDGE))) {
+        if (!isIfaceCreated(node.ovsdbId(), DEFAULT_TUNNEL)) {
             return DEVICE_CREATED;
         }
 
+        if (node.type().equals(NodeType.GATEWAY) && (
+                !isIfaceCreated(node.ovsdbId(), PATCH_ROUT_BRIDGE) ||
+                !isIfaceCreated(node.ovsdbId(), PATCH_INTG_BRIDGE) ||
+                !isIfaceCreated(node.ovsdbId(), node.uplink().get()))) {
+            return DEVICE_CREATED;
+        }
         return COMPLETE;
     }
 
     private boolean isIfaceCreated(DeviceId deviceId, String ifaceName) {
-        return deviceService.getPorts(deviceId).stream()
-                .filter(p -> p.annotations().value(PORT_NAME).contains(ifaceName) &&
-                        p.isEnabled())
+        Device device = deviceService.getDevice(deviceId);
+        if (device == null || !device.is(BridgeConfig.class)) {
+            return false;
+        }
+
+        BridgeConfig bridgeConfig =  device.as(BridgeConfig.class);
+        return bridgeConfig.getPorts().stream()
+                .filter(port -> port.annotations().value(PORT_NAME).equals(ifaceName))
                 .findAny()
                 .isPresent();
     }
 
-    private void createBridge(OpenstackNode node, String bridgeName, String dpid) {
+    private boolean isBridgeCreated(DeviceId deviceId, String bridgeName) {
+        Device device = deviceService.getDevice(deviceId);
+        if (device == null || !device.is(BridgeConfig.class)) {
+            return false;
+        }
+
+        BridgeConfig bridgeConfig =  device.as(BridgeConfig.class);
+        return bridgeConfig.getBridges().stream()
+                .filter(bridge -> bridge.name().equals(bridgeName))
+                .findAny()
+                .isPresent();
+    }
+
+    private void createBridge(OpenstackNode node, String bridgeName, DeviceId deviceId) {
         Device device = deviceService.getDevice(node.ovsdbId());
         if (device == null || !device.is(BridgeConfig.class)) {
             log.error("Failed to create integration bridge on {}", node.ovsdbId());
             return;
         }
 
-        List<ControllerInfo> controllers = clusterService.getNodes().stream()
-                .map(controller -> new ControllerInfo(controller.ip(), DEFAULT_OFPORT, "tcp"))
-                .collect(Collectors.toList());
+        // TODO fix this when we use single ONOS cluster for both openstackNode and vRouter
+        Set<IpAddress> controllerIps;
+        if (bridgeName.equals(ROUTER_BRIDGE)) {
+            controllerIps = Sets.newHashSet(node.routerController().get());
+        } else {
+            controllerIps = clusterService.getNodes().stream()
+                    .map(ControllerNode::ip)
+                    .collect(Collectors.toSet());
+        }
 
+        List<ControllerInfo> controllers = controllerIps.stream()
+                    .map(ip -> new ControllerInfo(ip, DEFAULT_OFPORT, DEFAULT_OF_PROTO))
+                    .collect(Collectors.toList());
+
+        String dpid = deviceId.toString().substring(DPID_BEGIN);
         BridgeDescription bridgeDesc = DefaultBridgeDescription.builder()
                 .name(bridgeName)
                 .failMode(BridgeDescription.FailMode.SECURE)
@@ -386,11 +412,15 @@
                 .controllers(controllers)
                 .build();
 
-        BridgeConfig bridgeConfig =  device.as(BridgeConfig.class);
+        BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
         bridgeConfig.addBridge(bridgeDesc);
     }
 
     private void createTunnelInterface(OpenstackNode node) {
+        if (isIfaceCreated(node.ovsdbId(), DEFAULT_TUNNEL)) {
+            return;
+        }
+
         Device device = deviceService.getDevice(node.ovsdbId());
         if (device == null || !device.is(InterfaceConfig.class)) {
             log.error("Failed to create tunnel interface on {}", node.ovsdbId());
@@ -405,11 +435,17 @@
                 .key(TunnelKeys.flowTunnelKey())
                 .build();
 
-        InterfaceConfig ifaceConfig =  device.as(InterfaceConfig.class);
+        InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
         ifaceConfig.addTunnelMode(DEFAULT_TUNNEL, tunnelDesc);
     }
 
     private void createPatchInterface(OpenstackNode node) {
+        checkArgument(node.type().equals(NodeType.GATEWAY));
+        if (isIfaceCreated(node.ovsdbId(), PATCH_INTG_BRIDGE) &&
+                isIfaceCreated(node.ovsdbId(), PATCH_ROUT_BRIDGE)) {
+            return;
+        }
+
         Device device = deviceService.getDevice(node.ovsdbId());
         if (device == null || !device.is(InterfaceConfig.class)) {
             log.error("Failed to create patch interfaces on {}", node.hostname());
@@ -428,21 +464,38 @@
                 .peer(PATCH_INTG_BRIDGE)
                 .build();
 
-        InterfaceConfig ifaceConfig =  device.as(InterfaceConfig.class);
+        InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
         ifaceConfig.addPatchMode(PATCH_INTG_BRIDGE, patchIntg);
         ifaceConfig.addPatchMode(PATCH_ROUT_BRIDGE, patchRout);
     }
 
+    private void addUplink(OpenstackNode node) {
+        checkArgument(node.type().equals(NodeType.GATEWAY));
+        if (isIfaceCreated(node.ovsdbId(), node.uplink().get())) {
+            return;
+        }
+
+        Device device = deviceService.getDevice(node.ovsdbId());
+        if (device == null || !device.is(BridgeConfig.class)) {
+            log.error("Failed to add port {} on {}", node.uplink().get(), node.ovsdbId());
+            return;
+        }
+
+        BridgeConfig bridgeConfig =  device.as(BridgeConfig.class);
+        bridgeConfig.addPort(BridgeName.bridgeName(ROUTER_BRIDGE),
+                             node.uplink().get());
+    }
+
     private boolean isOvsdbConnected(OpenstackNode node) {
         OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort);
-        OvsdbClientService client = controller.getOvsdbClient(ovsdb);
+        OvsdbClientService client = ovsdbController.getOvsdbClient(ovsdb);
         return deviceService.isAvailable(node.ovsdbId()) &&
                 client != null &&
                 client.isConnected();
     }
 
     private void connectOvsdb(OpenstackNode node) {
-        controller.connect(node.managementIp(), TpPort.tpPort(ovsdbPort));
+        ovsdbController.connect(node.managementIp(), TpPort.tpPort(ovsdbPort));
     }
 
     private Set<String> systemIfaces(OpenstackNode node) {
@@ -450,6 +503,7 @@
         if (node.type().equals(NodeType.GATEWAY)) {
             ifaces.add(PATCH_INTG_BRIDGE);
             ifaces.add(PATCH_ROUT_BRIDGE);
+            ifaces.add(node.uplink().get());
         }
         return ifaces;
     }
@@ -482,7 +536,11 @@
 
         @Override
         public void disconnected(Device device) {
-            log.debug("Device {} is disconnected", device.id());
+            OpenstackNode node = nodeByDeviceId(device.id());
+            if (node != null) {
+                log.warn("Device {} is disconnected", device.id());
+                setNodeState(node, NodeState.INCOMPLETE);
+            }
         }
     }
 
@@ -566,6 +624,7 @@
                     (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
 
             switch (event.type()) {
+                // TODO implement OVSDB port event so that we can handle updates on the OVSDB
                 case PORT_ADDED:
                     eventExecutor.execute(() -> bridgeHandler.portAdded(event.port()));
                     break;
@@ -640,7 +699,7 @@
                     oldNode = event.oldValue().value();
                     newNode = event.newValue().value();
 
-                    log.debug("Reloaded {}", newNode.hostname());
+                    log.info("Reloaded {}", newNode.hostname());
                     if (!newNode.equals(oldNode)) {
                         log.debug("New node: {}", newNode);
                     }
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
index d5cb8ed..84803c1 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
@@ -22,10 +22,14 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.Device;
+import org.onosproject.net.behaviour.BridgeConfig;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.PortDescription;
 import org.onosproject.openstacknode.OpenstackNode;
 import org.onosproject.openstacknode.OpenstackNodeService;
 
+import java.util.Optional;
+
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
 import static org.onosproject.openstacknode.Constants.*;
 import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
@@ -60,7 +64,7 @@
             return;
         }
 
-        print("%n[Integration Bridge Status]");
+        print("[Integration Bridge Status]");
         Device device = deviceService.getDevice(node.intBridge());
         if (device != null) {
             print("%s %s=%s available=%s %s",
@@ -79,23 +83,30 @@
         }
 
         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.intBridge(), PATCH_INTG_BRIDGE));
 
-                print(getPortState(deviceService, node.routerBridge().get(), PATCH_ROUT_BRIDGE));
-                print(getPortState(deviceService, node.intBridge(), PATCH_INTG_BRIDGE));
+            print("%n[Router Bridge Status]");
+            device = deviceService.getDevice(node.ovsdbId());
+            if (device == null || !device.is(BridgeConfig.class)) {
+                print("%s %s=%s is not available(unable to connect OVSDB)",
+                      MSG_NO,
+                      ROUTER_BRIDGE,
+                      node.intBridge());
             } else {
-                print("%s %s=%s is not available",
-                        MSG_NO,
-                        ROUTER_BRIDGE,
-                        node.intBridge());
+                BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
+                boolean available = bridgeConfig.getBridges().stream()
+                        .filter(bridge -> bridge.name().equals(ROUTER_BRIDGE))
+                        .findAny()
+                        .isPresent();
+
+                print("%s %s=%s available=%s",
+                      available ? MSG_OK : MSG_NO,
+                      ROUTER_BRIDGE,
+                      node.routerBridge().get(),
+                      available);
+
+                print(getPortStateOvsdb(deviceService, node.ovsdbId(), PATCH_ROUT_BRIDGE));
+                print(getPortStateOvsdb(deviceService, node.ovsdbId(), node.uplink().get()));
             }
         }
     }
@@ -117,4 +128,28 @@
             return String.format("%s %s does not exist", MSG_NO, portName);
         }
     }
+
+    private String getPortStateOvsdb(DeviceService deviceService, DeviceId deviceId, String portName) {
+        Device device = deviceService.getDevice(deviceId);
+        if (device == null || !device.is(BridgeConfig.class)) {
+            return String.format("%s %s does not exist(unable to connect OVSDB)",
+                                 MSG_NO, portName);
+        }
+
+        BridgeConfig bridgeConfig =  device.as(BridgeConfig.class);
+        Optional<PortDescription> port = bridgeConfig.getPorts().stream()
+                .filter(p -> p.annotations().value(PORT_NAME).contains(portName))
+                .findAny();
+
+        if (port.isPresent()) {
+            return String.format("%s %s portNum=%s enabled=%s %s",
+                                 port.get().isEnabled() ? MSG_OK : MSG_NO,
+                                 portName,
+                                 port.get().portNumber(),
+                                 port.get().isEnabled() ? Boolean.TRUE : Boolean.FALSE,
+                                 port.get().annotations());
+        } else {
+            return String.format("%s %s does not exist", MSG_NO, portName);
+        }
+    }
 }