CORD-333 Minimized OVSDB provider dependency

With this patch, cordvtn doesn't need to care for OVSDB connection state
anymore. It will make a connection to OVSDB server like befor but just
for node init and disconnect the OVSDB right after init is done.
- Changed OvsdbNode to CordVtnNode
- Removed OVSDB connect/disconnect and added initNode instead
- Changed ovsdb* commands to cordvtn-node* command, and removed
  connect/disconnect command and added init instead
- Fixed to remove OVSDB device from the system after node init or before
  making a connection to work around OVSDB device re-connect issue

Change-Id: If69369a06526947122494b2f7e816e37aa931f2c
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
index e15bc76..c3bf77c 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -15,7 +15,6 @@
  */
 package org.onosproject.cordvtn;
 
-import com.google.common.collect.Collections2;
 import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -32,6 +31,7 @@
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
+import org.onosproject.net.Port;
 import org.onosproject.net.behaviour.BridgeConfig;
 import org.onosproject.net.behaviour.BridgeName;
 import org.onosproject.net.behaviour.ControllerInfo;
@@ -39,6 +39,7 @@
 import org.onosproject.net.behaviour.TunnelConfig;
 import org.onosproject.net.behaviour.TunnelDescription;
 import org.onosproject.net.behaviour.TunnelName;
+import org.onosproject.net.device.DeviceAdminService;
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
@@ -54,7 +55,6 @@
 import org.onosproject.store.service.ConsistentMap;
 import org.onosproject.store.service.Serializer;
 import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.Versioned;
 import org.slf4j.Logger;
 
 import java.util.ArrayList;
@@ -84,7 +84,8 @@
     private static final int NUM_THREADS = 1;
     private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
             .register(KryoNamespaces.API)
-            .register(DefaultOvsdbNode.class);
+            .register(CordVtnNode.class)
+            .register(NodeState.class);
     private static final String DEFAULT_BRIDGE_NAME = "br-int";
     private static final String DEFAULT_TUNNEL = "vxlan";
     private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
@@ -112,6 +113,9 @@
     protected DriverService driverService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceAdminService adminService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OvsdbController controller;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -127,12 +131,55 @@
     private final BridgeHandler bridgeHandler = new BridgeHandler();
     private final VmHandler vmHandler = new VmHandler();
 
-    private ConsistentMap<DeviceId, OvsdbNode> nodeStore;
+    private ConsistentMap<CordVtnNode, NodeState> nodeStore;
+
+    private enum NodeState {
+
+        INIT {
+            @Override
+            public void process(CordVtn cordVtn, CordVtnNode node) {
+                cordVtn.connect(node);
+            }
+        },
+        OVSDB_CONNECTED {
+            @Override
+            public void process(CordVtn cordVtn, CordVtnNode node) {
+                if (!cordVtn.getOvsdbConnectionState(node)) {
+                    cordVtn.connect(node);
+                } else {
+                    cordVtn.createIntegrationBridge(node);
+                }
+            }
+        },
+        BRIDGE_CREATED {
+            @Override
+            public void process(CordVtn cordVtn, CordVtnNode node) {
+                if (!cordVtn.getOvsdbConnectionState(node)) {
+                    cordVtn.connect(node);
+                } else {
+                    cordVtn.createTunnelInterface(node);
+                }
+            }
+        },
+        COMPLETE {
+            @Override
+            public void process(CordVtn cordVtn, CordVtnNode node) {
+                cordVtn.postInit(node);
+            }
+        },
+        INCOMPLETE {
+            @Override
+            public void process(CordVtn cordVtn, CordVtnNode node) {
+            }
+        };
+
+        public abstract void process(CordVtn cordVtn, CordVtnNode node);
+    }
 
     @Activate
     protected void activate() {
         ApplicationId appId = coreService.registerApplication("org.onosproject.cordvtn");
-        nodeStore = storageService.<DeviceId, OvsdbNode>consistentMapBuilder()
+        nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder()
                 .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
                 .withName("cordvtn-nodestore")
                 .withApplicationId(appId)
@@ -156,79 +203,22 @@
     }
 
     @Override
-    public void addNode(OvsdbNode ovsdb) {
-        checkNotNull(ovsdb);
+    public void addNode(CordVtnNode node) {
+        checkNotNull(node);
 
-        nodeStore.putIfAbsent(ovsdb.deviceId(), ovsdb);
-
-        if (isNodeConnected(ovsdb)) {
-            init(ovsdb);
-        } else {
-            connect(ovsdb);
-        }
+        nodeStore.putIfAbsent(node, checkNodeState(node));
+        initNode(node);
     }
 
     @Override
-    public void deleteNode(OvsdbNode ovsdb) {
-        checkNotNull(ovsdb);
+    public void deleteNode(CordVtnNode node) {
+        checkNotNull(node);
 
-        if (deviceService.getDevice(ovsdb.deviceId()) != null) {
-            if (deviceService.isAvailable(ovsdb.deviceId())) {
-                log.warn("Cannot delete connected node {}", ovsdb.host());
-                return;
-            }
-        }
-        nodeStore.remove(ovsdb.deviceId());
-    }
-
-    @Override
-    public void connect(OvsdbNode ovsdb) {
-        checkNotNull(ovsdb);
-
-        if (!nodeStore.containsKey(ovsdb.deviceId())) {
-            log.warn("Node {} does not exist", ovsdb.host());
-            return;
+        if (getOvsdbConnectionState(node)) {
+            disconnect(node);
         }
 
-        if (!isNodeConnected(ovsdb)) {
-            controller.connect(ovsdb.ip(), ovsdb.port());
-        }
-    }
-
-    @Override
-    public void disconnect(OvsdbNode ovsdb) {
-        checkNotNull(ovsdb);
-
-        if (!nodeStore.containsKey(ovsdb.deviceId())) {
-            log.warn("Node {} does not exist", ovsdb.host());
-            return;
-        }
-
-        if (isNodeConnected(ovsdb)) {
-            OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
-            ovsdbClient.disconnect();
-        }
-    }
-
-    private void init(OvsdbNode ovsdb) {
-        checkNotNull(ovsdb);
-
-        if (!nodeStore.containsKey(ovsdb.deviceId())) {
-            log.warn("Node {} does not exist", ovsdb.host());
-            return;
-        }
-
-        if (!isNodeConnected(ovsdb)) {
-            log.warn("Node {} is not connected", ovsdb.host());
-            return;
-        }
-
-        if (deviceService.getDevice(ovsdb.intBrId()) == null ||
-                !deviceService.isAvailable(ovsdb.intBrId())) {
-            createIntegrationBridge(ovsdb);
-        } else if (!checkVxlanInterface(ovsdb)) {
-            createVxlanInterface(ovsdb);
-        }
+        nodeStore.remove(node);
     }
 
     @Override
@@ -237,64 +227,248 @@
     }
 
     @Override
-    public OvsdbNode getNode(DeviceId deviceId) {
-        Versioned<OvsdbNode> ovsdb = nodeStore.get(deviceId);
-        if (ovsdb != null) {
-            return ovsdb.value();
-        } else {
+    public List<CordVtnNode> getNodes() {
+        List<CordVtnNode> nodes = new ArrayList<>();
+        nodes.addAll(nodeStore.keySet());
+        return nodes;
+    }
+
+    @Override
+    public void initNode(CordVtnNode node) {
+        checkNotNull(node);
+
+        if (!nodeStore.containsKey(node)) {
+            log.warn("Node {} does not exist, add node first", node.hostname());
+            return;
+        }
+
+        NodeState state = getNodeState(node);
+        if (state == null) {
+            return;
+        } else if (state.equals(NodeState.INCOMPLETE)) {
+            state = checkNodeState(node);
+        }
+
+        state.process(this, node);
+    }
+
+    @Override
+    public boolean getNodeInitState(CordVtnNode node) {
+        checkNotNull(node);
+
+        NodeState state = getNodeState(node);
+        return state != null && state.equals(NodeState.COMPLETE);
+    }
+
+    /**
+     * Returns state of a given cordvtn node.
+     *
+     * @param node cordvtn node
+     * @return node state, or null if no such node exists
+     */
+    private NodeState getNodeState(CordVtnNode node) {
+        checkNotNull(node);
+
+        try {
+            return nodeStore.get(node).value();
+        } catch (NullPointerException e) {
+            log.error("Failed to get state of {}", node.hostname());
             return null;
         }
     }
 
-    @Override
-    public List<OvsdbNode> getNodes() {
-        List<OvsdbNode> ovsdbs = new ArrayList<>();
-        ovsdbs.addAll(Collections2.transform(nodeStore.values(), Versioned::value));
-        return ovsdbs;
+    /**
+     * Sets a new state for a given cordvtn node.
+     *
+     * @param node cordvtn node
+     * @param newState new node state
+     */
+    private void setNodeState(CordVtnNode node, NodeState newState) {
+        checkNotNull(node);
+
+        log.info("Changed {} state: {}", node.hostname(), newState.toString());
+
+        nodeStore.put(node, newState);
+        newState.process(this, node);
     }
 
-    @Override
-    public boolean isNodeConnected(OvsdbNode ovsdb) {
-        checkNotNull(ovsdb);
+    /**
+     * Checks current state of a given cordvtn node and returns it.
+     *
+     * @param node cordvtn node
+     * @return node state
+     */
+    private NodeState checkNodeState(CordVtnNode node) {
+        checkNotNull(node);
 
-        OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
-        if (ovsdbClient == null) {
-            return false;
+        if (checkIntegrationBridge(node) && checkTunnelInterface(node)) {
+            return NodeState.COMPLETE;
+        } else if (checkIntegrationBridge(node)) {
+            return NodeState.BRIDGE_CREATED;
+        } else if (getOvsdbConnectionState(node)) {
+            return NodeState.OVSDB_CONNECTED;
         } else {
-            return ovsdbClient.isConnected();
+            return NodeState.INIT;
         }
     }
 
-    private OvsdbClientService getOvsdbClient(OvsdbNode ovsdb) {
-        checkNotNull(ovsdb);
+    /**
+     * Performs tasks after node initialization.
+     *
+     * @param node cordvtn node
+     */
+    private void postInit(CordVtnNode node) {
+        disconnect(node);
+    }
+
+    /**
+     * Returns connection state of OVSDB server for a given node.
+     *
+     * @param node cordvtn node
+     * @return true if it is connected, false otherwise
+     */
+    private boolean getOvsdbConnectionState(CordVtnNode node) {
+        checkNotNull(node);
+
+        OvsdbClientService ovsdbClient = getOvsdbClient(node);
+        return deviceService.isAvailable(node.ovsdbId()) &&
+                ovsdbClient != null && ovsdbClient.isConnected();
+    }
+
+    /**
+     * Connects to OVSDB server for a given node.
+     *
+     * @param node cordvtn node
+     */
+    private void connect(CordVtnNode node) {
+        checkNotNull(node);
+
+        if (!nodeStore.containsKey(node)) {
+            log.warn("Node {} does not exist", node.hostname());
+            return;
+        }
+
+        if (!getOvsdbConnectionState(node)) {
+            // FIXME remove existing OVSDB device to work around OVSDB device re-connect issue
+            if (deviceService.getDevice(node.ovsdbId()) != null) {
+                adminService.removeDevice(node.ovsdbId());
+            }
+            controller.connect(node.ovsdbIp(), node.ovsdbPort());
+        }
+    }
+
+    /**
+     * Disconnects OVSDB server for a given node.
+     *
+     * @param node cordvtn node
+     */
+    private void disconnect(CordVtnNode node) {
+        checkNotNull(node);
+
+        if (!nodeStore.containsKey(node)) {
+            log.warn("Node {} does not exist", node.hostname());
+            return;
+        }
+
+        if (getOvsdbConnectionState(node)) {
+            OvsdbClientService ovsdbClient = getOvsdbClient(node);
+            ovsdbClient.disconnect();
+        }
+
+        // FIXME remove existing OVSDB device to work around OVSDB device re-connect issue
+        if (deviceService.getDevice(node.ovsdbId()) != null) {
+            adminService.removeDevice(node.ovsdbId());
+        }
+    }
+
+    /**
+     * Returns cordvtn node associated with a given OVSDB device.
+     *
+     * @param ovsdbId OVSDB device id
+     * @return cordvtn node, null if it fails to find the node
+     */
+    private CordVtnNode getNodeByOvsdbId(DeviceId ovsdbId) {
+        try {
+            return getNodes().stream()
+                    .filter(node -> node.ovsdbId().equals(ovsdbId))
+                    .findFirst().get();
+        } catch (NoSuchElementException e) {
+            log.debug("Couldn't find node information for {}", ovsdbId);
+            return null;
+        }
+    }
+
+    /**
+     * Returns cordvtn node associated with a given integration bridge.
+     *
+     * @param bridgeId device id of integration bridge
+     * @return cordvtn node, null if it fails to find the node
+     */
+    private CordVtnNode getNodeByBridgeId(DeviceId bridgeId) {
+        try {
+            return getNodes().stream()
+                    .filter(node -> node.intBrId().equals(bridgeId))
+                    .findFirst().get();
+        } catch (NoSuchElementException e) {
+            log.debug("Couldn't find node information for {}", bridgeId);
+            return null;
+        }
+    }
+
+    /**
+     * Returns OVSDB client for a given node.
+     *
+     * @param node cordvtn node
+     * @return OVSDB client, or null if it fails to get OVSDB client
+     */
+    private OvsdbClientService getOvsdbClient(CordVtnNode node) {
+        checkNotNull(node);
 
         OvsdbClientService ovsdbClient = controller.getOvsdbClient(
-                new OvsdbNodeId(ovsdb.ip(), ovsdb.port().toInt()));
+                new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt()));
         if (ovsdbClient == null) {
-            log.debug("Couldn't find ovsdb client for {}", ovsdb.host());
+            log.debug("Couldn't find OVSDB client for {}", node.hostname());
         }
         return ovsdbClient;
     }
 
-    private void createIntegrationBridge(OvsdbNode ovsdb) {
+    /**
+     * Creates an integration bridge for a given node.
+     *
+     * @param node cordvtn node
+     */
+    private void createIntegrationBridge(CordVtnNode node) {
+        if (checkIntegrationBridge(node)) {
+            return;
+        }
+
         List<ControllerInfo> controllers = new ArrayList<>();
         Sets.newHashSet(clusterService.getNodes())
                 .forEach(controller -> {
                     ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
                     controllers.add(ctrlInfo);
                 });
-        String dpid = ovsdb.intBrId().toString().substring(DPID_BEGIN);
+        String dpid = node.intBrId().toString().substring(DPID_BEGIN);
 
         try {
-            DriverHandler handler = driverService.createHandler(ovsdb.deviceId());
+            DriverHandler handler = driverService.createHandler(node.ovsdbId());
             BridgeConfig bridgeConfig =  handler.behaviour(BridgeConfig.class);
             bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), dpid, controllers);
         } catch (ItemNotFoundException e) {
-            log.warn("Failed to create integration bridge on {}", ovsdb.deviceId());
+            log.warn("Failed to create integration bridge on {}", node.ovsdbId());
         }
     }
 
-    private void createVxlanInterface(OvsdbNode ovsdb) {
+    /**
+     * Creates tunnel interface to the integration bridge for a given node.
+     *
+     * @param node cordvtn node
+     */
+    private void createTunnelInterface(CordVtnNode node) {
+        if (checkTunnelInterface(node)) {
+            return;
+        }
+
         DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
         for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
             optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
@@ -304,38 +478,63 @@
                                              TunnelName.tunnelName(DEFAULT_TUNNEL),
                                              optionBuilder.build());
         try {
-            DriverHandler handler = driverService.createHandler(ovsdb.deviceId());
+            DriverHandler handler = driverService.createHandler(node.ovsdbId());
             TunnelConfig tunnelConfig =  handler.behaviour(TunnelConfig.class);
             tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), description);
         } catch (ItemNotFoundException e) {
-            log.warn("Failed to create VXLAN interface on {}", ovsdb.deviceId());
+            log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
         }
     }
 
-    private boolean checkVxlanInterface(OvsdbNode ovsdb) {
+    /**
+     * Checks if integration bridge exists and available.
+     *
+     * @param node cordvtn node
+     * @return true if the bridge is available, false otherwise
+     */
+    private boolean checkIntegrationBridge(CordVtnNode node) {
+        return (deviceService.getDevice(node.intBrId()) != null
+                && deviceService.isAvailable(node.intBrId()));
+    }
+
+    /**
+     * Checks if tunnel interface exists.
+     *
+     * @param node cordvtn node
+     * @return true if the interface exists, false otherwise
+     */
+    private boolean checkTunnelInterface(CordVtnNode node) {
         try {
-            DriverHandler handler = driverService.createHandler(ovsdb.deviceId());
-            BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
-            bridgeConfig.getPorts().stream()
-                    .filter(p -> p.annotations().value("portName").equals(DEFAULT_TUNNEL))
+            deviceService.getPorts(node.intBrId())
+                    .stream()
+                    .filter(p -> p.annotations().value("portName").contains(DEFAULT_TUNNEL)
+                            && p.isEnabled())
                     .findAny().get();
-        } catch (ItemNotFoundException | NoSuchElementException e) {
+            return true;
+        } catch (NoSuchElementException e) {
             return false;
         }
-        return true;
     }
 
     private class InternalDeviceListener implements DeviceListener {
 
         @Override
         public void event(DeviceEvent event) {
+
             Device device = event.subject();
-            ConnectionHandler handler = (device.type() == SWITCH ? bridgeHandler : ovsdbHandler);
+            ConnectionHandler<Device> handler =
+                    (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
 
             switch (event.type()) {
-                case DEVICE_ADDED:
-                    eventExecutor.submit(() -> handler.connected(device));
+                case PORT_ADDED:
+                    eventExecutor.submit(() -> bridgeHandler.portAdded(event.port()));
                     break;
+                case PORT_UPDATED:
+                    if (!event.port().isEnabled()) {
+                        eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port()));
+                    }
+                    break;
+                case DEVICE_ADDED:
                 case DEVICE_AVAILABILITY_CHANGED:
                     if (deviceService.isAvailable(device.id())) {
                         eventExecutor.submit(() -> handler.connected(device));
@@ -372,17 +571,15 @@
 
         @Override
         public void connected(Device device) {
-            log.info("Ovsdb {} is connected", device.id());
-
-            OvsdbNode ovsdb = getNode(device.id());
-            if (ovsdb != null) {
-                init(ovsdb);
+            CordVtnNode node = getNodeByOvsdbId(device.id());
+            if (node != null) {
+                setNodeState(node, checkNodeState(node));
             }
         }
 
         @Override
         public void disconnected(Device device) {
-            log.warn("Ovsdb {} is disconnected", device.id());
+            log.info("OVSDB {} is disconnected", device.id());
         }
     }
 
@@ -390,26 +587,56 @@
 
         @Override
         public void connected(Device device) {
-            log.info("Integration Bridge {} is detected", device.id());
-
-            OvsdbNode ovsdb;
-            try {
-                ovsdb = getNodes().stream()
-                        .filter(node -> node.intBrId().equals(device.id()))
-                        .findFirst().get();
-            } catch (NoSuchElementException e) {
-                log.warn("Couldn't find OVSDB associated with {}", device.id());
-                return;
-            }
-
-            if (!checkVxlanInterface(ovsdb)) {
-                createVxlanInterface(ovsdb);
+            CordVtnNode node = getNodeByBridgeId(device.id());
+            if (node != null) {
+                setNodeState(node, checkNodeState(node));
             }
         }
 
         @Override
         public void disconnected(Device device) {
-            log.info("Integration Bridge {} is vanished", device.id());
+            CordVtnNode node = getNodeByBridgeId(device.id());
+            if (node != null) {
+                log.info("Integration Bridge is disconnected from {}", node.hostname());
+                setNodeState(node, NodeState.INCOMPLETE);
+            }
+        }
+
+        /**
+         * Handles port added situation.
+         * If the added port is tunnel port, proceed remaining node initialization.
+         * Otherwise, do nothing.
+         *
+         * @param port port
+         */
+        public void portAdded(Port port) {
+            if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
+                return;
+            }
+
+            CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
+            if (node != null) {
+                setNodeState(node, checkNodeState(node));
+            }
+        }
+
+        /**
+         * Handles port removed situation.
+         * If the removed port is tunnel port, proceed remaining node initialization.
+         * Others, do nothing.
+         *
+         * @param port port
+         */
+        public void portRemoved(Port port) {
+            if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
+                return;
+            }
+
+            CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
+            if (node != null) {
+                log.info("Tunnel interface is removed from {}", node.hostname());
+                setNodeState(node, NodeState.INCOMPLETE);
+            }
         }
     }
 
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java
index 550452c..827ce05 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java
@@ -32,77 +32,82 @@
  */
 public class CordVtnConfig extends Config<ApplicationId> {
 
-    public static final String OVSDB_NODES = "ovsdbNodes";
-    public static final String HOST = "host";
-    public static final String IP = "ip";
-    public static final String PORT = "port";
+    public static final String CORDVTN_NODES = "nodes";
+    public static final String HOSTNAME = "hostname";
+    public static final String OVSDB_IP = "ovsdbIp";
+    public static final String OVSDB_PORT = "ovsdbPort";
     public static final String BRIDGE_ID = "bridgeId";
 
     /**
-     * Returns the set of ovsdb nodes read from network config.
+     * Returns the set of nodes read from network config.
      *
-     * @return set of OvsdbNodeConfig or null
+     * @return set of CordVtnNodeConfig or null
      */
-    public Set<OvsdbNodeConfig> ovsdbNodes() {
-        Set<OvsdbNodeConfig> ovsdbNodes = Sets.newHashSet();
+    public Set<CordVtnNodeConfig> cordVtnNodes() {
+        Set<CordVtnNodeConfig> nodes = Sets.newHashSet();
 
-        JsonNode nodes = object.get(OVSDB_NODES);
-        if (nodes == null) {
+        JsonNode jsonNodes = object.get(CORDVTN_NODES);
+        if (jsonNodes == null) {
             return null;
         }
-        nodes.forEach(jsonNode -> ovsdbNodes.add(new OvsdbNodeConfig(
-            jsonNode.path(HOST).asText(),
-            IpAddress.valueOf(jsonNode.path(IP).asText()),
-            TpPort.tpPort(jsonNode.path(PORT).asInt()),
+        jsonNodes.forEach(jsonNode -> nodes.add(new CordVtnNodeConfig(
+            jsonNode.path(HOSTNAME).asText(),
+            IpAddress.valueOf(jsonNode.path(OVSDB_IP).asText()),
+            TpPort.tpPort(jsonNode.path(OVSDB_PORT).asInt()),
             DeviceId.deviceId(jsonNode.path(BRIDGE_ID).asText()))));
 
-        return ovsdbNodes;
+        return nodes;
     }
 
     /**
-     * Configuration for an ovsdb node.
+     * Configuration for CordVtn node.
      */
-    public static class OvsdbNodeConfig {
+    public static class CordVtnNodeConfig {
 
-        private final String host;
-        private final IpAddress ip;
-        private final TpPort port;
+        private final String hostname;
+        private final IpAddress ovsdbIp;
+        private final TpPort ovsdbPort;
         private final DeviceId bridgeId;
 
-        public OvsdbNodeConfig(String host, IpAddress ip, TpPort port, DeviceId bridgeId) {
-            this.host = checkNotNull(host);
-            this.ip = checkNotNull(ip);
-            this.port = checkNotNull(port);
+        public CordVtnNodeConfig(String hostname, IpAddress ovsdbIp, TpPort ovsdbPort, DeviceId bridgeId) {
+            this.hostname = checkNotNull(hostname);
+            this.ovsdbIp = checkNotNull(ovsdbIp);
+            this.ovsdbPort = checkNotNull(ovsdbPort);
             this.bridgeId = checkNotNull(bridgeId);
         }
 
         /**
-         * Returns host information of the node.
+         * Returns hostname of the node.
          *
-         * @return host
+         * @return hostname
          */
-        public String host() {
-            return this.host;
+        public String hostname() {
+            return this.hostname;
         }
 
         /**
-         * Returns ip address to access ovsdb-server of the node.
+         * Returns OVSDB ip address of the node.
          *
-         * @return ip address
+         * @return OVSDB server IP address
          */
-        public IpAddress ip() {
-            return this.ip;
+        public IpAddress ovsdbIp() {
+            return this.ovsdbIp;
         }
 
         /**
-         * Returns port number to access ovsdb-server of the node.
+         * Returns OVSDB port number of the node.
          *
          * @return port number
          */
-        public TpPort port() {
-            return this.port;
+        public TpPort ovsdbPort() {
+            return this.ovsdbPort;
         }
 
+        /**
+         * Returns integration bridge id of the node.
+         *
+         * @return device id
+         */
         public DeviceId bridgeId() {
             return this.bridgeId;
         }
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
index 274ca9b..f79b446 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
@@ -88,10 +88,10 @@
             return;
         }
 
-        config.ovsdbNodes().forEach(node -> {
-            DefaultOvsdbNode ovsdb = new DefaultOvsdbNode(
-                    node.host(), node.ip(), node.port(), node.bridgeId());
-            cordVtnService.addNode(ovsdb);
+        config.cordVtnNodes().forEach(node -> {
+            CordVtnNode cordVtnNode = new CordVtnNode(
+                    node.hostname(), node.ovsdbIp(), node.ovsdbPort(), node.bridgeId());
+            cordVtnService.addNode(cordVtnNode);
         });
     }
 
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnNode.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnNode.java
new file mode 100644
index 0000000..439d16e
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnNode.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2014-2015 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.cordvtn;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.net.DeviceId;
+
+import java.util.Comparator;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a compute infrastructure node for CORD VTN service.
+ */
+public final class CordVtnNode {
+
+    private final String hostname;
+    private final IpAddress ovsdbIp;
+    private final TpPort ovsdbPort;
+    private final DeviceId bridgeId;
+
+    public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR =
+            (node1, node2) -> node1.hostname().compareTo(node2.hostname());
+
+    /**
+     * Creates a new node.
+     *
+     * @param hostname hostname
+     * @param ovsdbIp OVSDB server IP address
+     * @param ovsdbPort OVSDB server port number
+     * @param bridgeId integration bridge identifier
+     */
+    public CordVtnNode(String hostname, IpAddress ovsdbIp, TpPort ovsdbPort, DeviceId bridgeId) {
+        this.hostname = checkNotNull(hostname);
+        this.ovsdbIp = checkNotNull(ovsdbIp);
+        this.ovsdbPort = checkNotNull(ovsdbPort);
+        this.bridgeId = checkNotNull(bridgeId);
+    }
+
+    /**
+     * Returns the OVSDB server IP address.
+     *
+     * @return ip address
+     */
+    public IpAddress ovsdbIp() {
+        return this.ovsdbIp;
+    }
+
+    /**
+     * Returns the OVSDB server port number.
+     *
+     * @return port number
+     */
+    public TpPort ovsdbPort() {
+        return this.ovsdbPort;
+    }
+
+    /**
+     * Returns the hostname.
+     *
+     * @return hostname
+     */
+    public String hostname() {
+        return this.hostname;
+    }
+
+    /**
+     * Returns the identifier of the integration bridge.
+     *
+     * @return device id
+     */
+    public DeviceId intBrId() {
+        return this.bridgeId;
+    }
+
+    /**
+     * Returns the identifier of the OVSDB device.
+     *
+     * @return device id
+     */
+    public DeviceId ovsdbId() {
+        return DeviceId.deviceId("ovsdb:" + this.ovsdbIp.toString());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof CordVtnNode) {
+            CordVtnNode that = (CordVtnNode) obj;
+            if (Objects.equals(hostname, that.hostname) &&
+                    Objects.equals(ovsdbIp, that.ovsdbIp) &&
+                    Objects.equals(ovsdbPort, that.ovsdbPort) &&
+                    Objects.equals(bridgeId, that.bridgeId)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(hostname, ovsdbIp, ovsdbPort);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("host", hostname)
+                .add("ip", ovsdbIp)
+                .add("port", ovsdbPort)
+                .add("bridgeId", bridgeId)
+                .toString();
+    }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
index 7e01a45..5ab7baf 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
@@ -15,8 +15,6 @@
  */
 package org.onosproject.cordvtn;
 
-import org.onosproject.net.DeviceId;
-
 import java.util.List;
 
 /**
@@ -28,30 +26,23 @@
     /**
      * Adds a new node to the service.
      *
-     * @param ovsdb ovsdb node
+     * @param node cordvtn node
      */
-    void addNode(OvsdbNode ovsdb);
+    void addNode(CordVtnNode node);
 
     /**
      * Deletes a node from the service.
      *
-     * @param ovsdb ovsdb node
+     * @param node cordvtn node
      */
-    void deleteNode(OvsdbNode ovsdb);
+    void deleteNode(CordVtnNode node);
 
     /**
-     * Connect to a node.
+     * Initiates node to serve virtual tenant network.
      *
-     * @param ovsdb ovsdb node
+     * @param node cordvtn node
      */
-    void connect(OvsdbNode ovsdb);
-
-    /**
-     * Disconnect a node.
-     *
-     * @param ovsdb ovsdb node
-     */
-    void disconnect(OvsdbNode ovsdb);
+    void initNode(CordVtnNode node);
 
     /**
      * Returns the number of the nodes known to the service.
@@ -61,25 +52,17 @@
     int getNodeCount();
 
     /**
-     * Returns OvsdbNode with given device id.
+     * Returns node initialization state.
      *
-     * @param deviceId device id
-     * @return ovsdb node
+     * @param node cordvtn node
+     * @return true if initial node setup is completed, otherwise false
      */
-    OvsdbNode getNode(DeviceId deviceId);
-
-    /**
-     * Returns connection state of the node.
-     *
-     * @param ovsdb ovsdb node
-     * @return true if the node is connected, false otherwise
-     */
-    boolean isNodeConnected(OvsdbNode ovsdb);
+    boolean getNodeInitState(CordVtnNode node);
 
     /**
      * Returns all nodes known to the service.
      *
      * @return list of nodes
      */
-    List<OvsdbNode> getNodes();
+    List<CordVtnNode> getNodes();
 }
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
deleted file mode 100644
index 46f6e29..0000000
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2014-2015 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.cordvtn;
-
-import com.google.common.base.MoreObjects;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.TpPort;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * OvsdbNode implementation.
- */
-public class DefaultOvsdbNode implements OvsdbNode {
-
-    private final String host;
-    private final IpAddress ip;
-    private final TpPort port;
-    private final DeviceId brId;
-
-    public DefaultOvsdbNode(String host, IpAddress ip, TpPort port, DeviceId brId) {
-        this.host = host;
-        this.ip = ip;
-        this.port = port;
-        this.brId = brId;
-    }
-
-    @Override
-    public IpAddress ip() {
-        return this.ip;
-    }
-
-    @Override
-    public TpPort port() {
-        return this.port;
-    }
-
-    @Override
-    public String host() {
-        return this.host;
-    }
-
-    @Override
-    public DeviceId intBrId() {
-        return this.brId;
-    }
-
-    @Override
-    public DeviceId deviceId() {
-        return DeviceId.deviceId("ovsdb:" + this.ip.toString());
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (o instanceof DefaultOvsdbNode) {
-            DefaultOvsdbNode that = (DefaultOvsdbNode) o;
-            if (this.host.equals(that.host) &&
-                    this.ip.equals(that.ip) &&
-                    this.port.equals(that.port) &&
-                    this.brId.equals(that.brId)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(host, ip, port);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .add("host", host)
-                .add("ip", ip)
-                .add("port", port)
-                .add("bridgeId", brId)
-                .toString();
-    }
-}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
deleted file mode 100644
index 7a9a06a..0000000
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2014-2015 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.cordvtn;
-
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.TpPort;
-import org.onosproject.net.DeviceId;
-
-import java.util.Comparator;
-
-/**
- * Representation of a node with ovsdb server.
- */
-public interface OvsdbNode {
-
-    Comparator<OvsdbNode> OVSDB_NODE_COMPARATOR = new Comparator<OvsdbNode>() {
-        @Override
-        public int compare(OvsdbNode ovsdb1, OvsdbNode ovsdb2) {
-            return ovsdb1.host().compareTo(ovsdb2.host());
-        }
-    };
-
-    /**
-     * Returns the IP address of the ovsdb server.
-     *
-     * @return ip address
-     */
-    IpAddress ip();
-
-    /**
-     * Returns the port number of the ovsdb server.
-     *
-     * @return port number
-     */
-    TpPort port();
-
-    /**
-     * Returns the host information of the ovsdb server.
-     * It could be hostname or ip address.
-     *
-     * @return host
-     */
-    String host();
-
-    /**
-     * Returns the device id of the ovsdb server.
-     *
-     * @return device id
-     */
-    DeviceId deviceId();
-
-    /**
-     * Returns the device id of the integration bridge associated with the node.
-     *
-     * @return device id
-     */
-    DeviceId intBrId();
-}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeAddCommand.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeAddCommand.java
similarity index 63%
rename from apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeAddCommand.java
rename to apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeAddCommand.java
index 88d1634..1b7d986 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeAddCommand.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeAddCommand.java
@@ -22,27 +22,26 @@
 import org.onlab.packet.TpPort;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cordvtn.CordVtnService;
-import org.onosproject.cordvtn.DefaultOvsdbNode;
-import org.onosproject.cordvtn.OvsdbNode;
+import org.onosproject.cordvtn.CordVtnNode;
 import org.onosproject.net.DeviceId;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
 /**
- * Adds a new OVSDB nodes.
+ * Adds a new node to the service.
  */
-@Command(scope = "onos", name = "ovsdb-add",
-        description = "Adds a new OVSDB node to cordvtn")
-public class OvsdbNodeAddCommand extends AbstractShellCommand {
+@Command(scope = "onos", name = "cordvtn-node-add",
+        description = "Adds a new node to CORD VTN service")
+public class CordVtnNodeAddCommand extends AbstractShellCommand {
 
-    @Argument(index = 0, name = "host", description = "Hostname or IP",
+    @Argument(index = 0, name = "hostname", description = "Hostname",
             required = true, multiValued = false)
-    private String host = null;
+    private String hostname = null;
 
-    @Argument(index = 1, name = "address",
+    @Argument(index = 1, name = "ovsdb",
             description = "OVSDB server listening address (ip:port)",
             required = true, multiValued = false)
-    private String address = null;
+    private String ovsdb = null;
 
     @Argument(index = 2, name = "bridgeId",
             description = "Device ID of integration bridge",
@@ -51,15 +50,15 @@
 
     @Override
     protected void execute() {
-        checkArgument(address.contains(":"), "address should be ip:port format");
+        checkArgument(ovsdb.contains(":"), "OVSDB address should be ip:port format");
         checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format");
 
         CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
-        String[] ipPort = address.split(":");
-        OvsdbNode ovsdb = new DefaultOvsdbNode(host,
-                                               IpAddress.valueOf(ipPort[0]),
-                                               TpPort.tpPort(Integer.parseInt(ipPort[1])),
-                                               DeviceId.deviceId(bridgeId));
-        service.addNode(ovsdb);
+        String[] ipPort = ovsdb.split(":");
+        CordVtnNode node = new CordVtnNode(hostname,
+                                           IpAddress.valueOf(ipPort[0]),
+                                           TpPort.tpPort(Integer.parseInt(ipPort[1])),
+                                           DeviceId.deviceId(bridgeId));
+        service.addNode(node);
     }
 }
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeDeleteCommand.java
similarity index 64%
copy from apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java
copy to apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeDeleteCommand.java
index a500d0d..0446fc6 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeDeleteCommand.java
@@ -20,38 +20,38 @@
 import org.apache.karaf.shell.commands.Command;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cordvtn.CordVtnService;
-import org.onosproject.cordvtn.OvsdbNode;
+import org.onosproject.cordvtn.CordVtnNode;
 
 import java.util.NoSuchElementException;
 
 /**
- * Deletes OVSDB nodes from cordvtn.
+ * Deletes nodes from the service.
  */
-@Command(scope = "onos", name = "ovsdb-delete",
-        description = "Deletes OVSDB nodes from cordvtn")
-public class OvsdbNodeDeleteCommand extends AbstractShellCommand {
+@Command(scope = "onos", name = "cordvtn-node-delete",
+        description = "Deletes nodes from CORD VTN service")
+public class CordVtnNodeDeleteCommand extends AbstractShellCommand {
 
-    @Argument(index = 0, name = "hosts", description = "Hostname(s) or IP(s)",
+    @Argument(index = 0, name = "hostnames", description = "Hostname(s)",
             required = true, multiValued = true)
-    private String[] hosts = null;
+    private String[] hostnames = null;
 
     @Override
     protected void execute() {
         CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
 
-        for (String host : hosts) {
-            OvsdbNode ovsdb;
+        for (String hostname : hostnames) {
+            CordVtnNode node;
             try {
-                ovsdb = service.getNodes().stream()
-                        .filter(node -> node.host().equals(host))
+                node = service.getNodes()
+                        .stream()
+                        .filter(n -> n.hostname().equals(hostname))
                         .findFirst().get();
-
             } catch (NoSuchElementException e) {
-                print("Unable to find %s", host);
+                print("Unable to find %s", hostname);
                 continue;
             }
 
-            service.deleteNode(ovsdb);
+            service.deleteNode(node);
         }
     }
 }
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeInitCommand.java
similarity index 64%
rename from apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java
rename to apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeInitCommand.java
index a500d0d..dd77a9c 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeInitCommand.java
@@ -20,38 +20,38 @@
 import org.apache.karaf.shell.commands.Command;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cordvtn.CordVtnService;
-import org.onosproject.cordvtn.OvsdbNode;
+import org.onosproject.cordvtn.CordVtnNode;
 
 import java.util.NoSuchElementException;
 
 /**
- * Deletes OVSDB nodes from cordvtn.
+ * Initializes nodes for CordVtn service.
  */
-@Command(scope = "onos", name = "ovsdb-delete",
-        description = "Deletes OVSDB nodes from cordvtn")
-public class OvsdbNodeDeleteCommand extends AbstractShellCommand {
+@Command(scope = "onos", name = "cordvtn-node-init",
+        description = "Initializes nodes for CORD VTN service")
+public class CordVtnNodeInitCommand extends AbstractShellCommand {
 
-    @Argument(index = 0, name = "hosts", description = "Hostname(s) or IP(s)",
+    @Argument(index = 0, name = "hostnames", description = "Hostname(s)",
             required = true, multiValued = true)
-    private String[] hosts = null;
+    private String[] hostnames = null;
 
     @Override
     protected void execute() {
         CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
 
-        for (String host : hosts) {
-            OvsdbNode ovsdb;
+        for (String hostname : hostnames) {
+            CordVtnNode node;
             try {
-                ovsdb = service.getNodes().stream()
-                        .filter(node -> node.host().equals(host))
+                node = service.getNodes()
+                        .stream()
+                        .filter(n -> n.hostname().equals(hostname))
                         .findFirst().get();
-
             } catch (NoSuchElementException e) {
-                print("Unable to find %s", host);
+                print("Unable to find %s", hostname);
                 continue;
             }
 
-            service.deleteNode(ovsdb);
+            service.initNode(node);
         }
     }
 }
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeListCommand.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeListCommand.java
new file mode 100644
index 0000000..83e5859
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeListCommand.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 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.cordvtn.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.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.CordVtnNode;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all nodes registered to the service.
+ */
+@Command(scope = "onos", name = "cordvtn-nodes",
+        description = "Lists all nodes registered in CORD VTN service")
+public class CordVtnNodeListCommand extends AbstractShellCommand {
+
+    @Override
+    protected void execute() {
+        CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+        List<CordVtnNode> nodes = service.getNodes();
+        Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR);
+
+        if (outputJson()) {
+            print("%s", json(service, nodes));
+        } else {
+            for (CordVtnNode node : nodes) {
+                print("hostname=%s, ovsdb=%s, br-int=%s, init=%s",
+                      node.hostname(),
+                      node.ovsdbIp().toString() + ":" + node.ovsdbPort().toString(),
+                      node.intBrId().toString(),
+                      getState(service, node));
+            }
+            print("Total %s nodes", service.getNodeCount());
+        }
+    }
+
+    private JsonNode json(CordVtnService service, List<CordVtnNode> nodes) {
+        ObjectMapper mapper = new ObjectMapper();
+        ArrayNode result = mapper.createArrayNode();
+        for (CordVtnNode node : nodes) {
+            String ipPort = node.ovsdbIp().toString() + ":" + node.ovsdbPort().toString();
+            result.add(mapper.createObjectNode()
+                               .put("hostname", node.hostname())
+                               .put("ovsdb", ipPort)
+                               .put("brInt", node.intBrId().toString())
+                               .put("init", getState(service, node)));
+        }
+        return result;
+    }
+
+    private String getState(CordVtnService service, CordVtnNode node) {
+        return service.getNodeInitState(node) ? "COMPLETE" : "INCOMPLETE";
+    }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeConnectCommand.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeConnectCommand.java
deleted file mode 100644
index e4ca0f3..0000000
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeConnectCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2015 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.cordvtn.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cordvtn.CordVtnService;
-import org.onosproject.cordvtn.OvsdbNode;
-
-import java.util.NoSuchElementException;
-
-/**
- * Connects to OVSDBs.
- */
-@Command(scope = "onos", name = "ovsdb-connect",
-        description = "Connects to OVSDBs")
-public class OvsdbNodeConnectCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "hosts", description = "Hostname(s) or IP(s)",
-            required = true, multiValued = true)
-    private String[] hosts = null;
-
-    @Override
-    protected void execute() {
-        CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
-
-        for (String host : hosts) {
-            OvsdbNode ovsdb;
-            try {
-                ovsdb = service.getNodes().stream()
-                        .filter(node -> node.host().equals(host))
-                        .findFirst().get();
-            } catch (NoSuchElementException e) {
-                print("Unable to find %s", host);
-                continue;
-            }
-
-            if (service.isNodeConnected(ovsdb)) {
-                print("OVSDB %s is already in connected state, do nothing", host);
-            } else {
-                service.connect(ovsdb);
-            }
-        }
-    }
-}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDisconnectCommand.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDisconnectCommand.java
deleted file mode 100644
index 14e44e0..0000000
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDisconnectCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2015 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.cordvtn.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cordvtn.CordVtnService;
-import org.onosproject.cordvtn.OvsdbNode;
-
-import java.util.NoSuchElementException;
-
-/**
- * Disconnects OVSDBs.
- */
-@Command(scope = "onos", name = "ovsdb-disconnect",
-        description = "Disconnects OVSDBs")
-public class OvsdbNodeDisconnectCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "hosts", description = "Hostname(s) or IP(s)",
-            required = true, multiValued = true)
-    private String[] hosts = null;
-
-    @Override
-    protected void execute() {
-        CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
-
-        for (String host : hosts) {
-            OvsdbNode ovsdb;
-            try {
-                ovsdb = service.getNodes().stream()
-                        .filter(node -> node.host().equals(host))
-                        .findFirst().get();
-            } catch (NoSuchElementException e) {
-                print("Unable to find %s", host);
-                continue;
-            }
-
-            if (!service.isNodeConnected(ovsdb)) {
-                print("OVSDB %s is already in disconnected state, do nothing", host);
-            } else {
-                service.disconnect(ovsdb);
-            }
-        }
-    }
-}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeListCommand.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeListCommand.java
deleted file mode 100644
index 7d125ca..0000000
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeListCommand.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2015 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.cordvtn.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.cordvtn.CordVtnService;
-import org.onosproject.cordvtn.OvsdbNode;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Lists all OVSDB nodes.
- */
-@Command(scope = "onos", name = "ovsdbs",
-        description = "Lists all OVSDB nodes registered in cordvtn application")
-public class OvsdbNodeListCommand extends AbstractShellCommand {
-
-    @Override
-    protected void execute() {
-        CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
-        List<OvsdbNode> ovsdbs = service.getNodes();
-        Collections.sort(ovsdbs, OvsdbNode.OVSDB_NODE_COMPARATOR);
-
-        if (outputJson()) {
-            print("%s", json(service, ovsdbs));
-        } else {
-            for (OvsdbNode ovsdb : ovsdbs) {
-                print("host=%s, address=%s, br-int=%s, state=%s",
-                      ovsdb.host(),
-                      ovsdb.ip().toString() + ":" + ovsdb.port().toString(),
-                      ovsdb.intBrId().toString(),
-                      getState(service, ovsdb));
-            }
-            print("Total %s nodes", service.getNodeCount());
-        }
-    }
-
-    private JsonNode json(CordVtnService service, List<OvsdbNode> ovsdbs) {
-        ObjectMapper mapper = new ObjectMapper();
-        ArrayNode result = mapper.createArrayNode();
-        for (OvsdbNode ovsdb : ovsdbs) {
-            String ipPort = ovsdb.ip().toString() + ":" + ovsdb.port().toString();
-            result.add(mapper.createObjectNode()
-                               .put("host", ovsdb.host())
-                               .put("address", ipPort)
-                               .put("brInt", ovsdb.intBrId().toString())
-                               .put("state", getState(service, ovsdb)));
-        }
-        return result;
-    }
-
-    private String getState(CordVtnService service, OvsdbNode ovsdb) {
-        return service.isNodeConnected(ovsdb) ? "CONNECTED" : "DISCONNECTED";
-    }
-}
diff --git a/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 6e17238..ad28bc7 100644
--- a/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -17,19 +17,16 @@
 
     <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
         <command>
-            <action class="org.onosproject.cordvtn.cli.OvsdbNodeListCommand"/>
+            <action class="org.onosproject.cordvtn.cli.CordVtnNodeListCommand"/>
         </command>
         <command>
-            <action class="org.onosproject.cordvtn.cli.OvsdbNodeAddCommand"/>
+            <action class="org.onosproject.cordvtn.cli.CordVtnNodeAddCommand"/>
         </command>
         <command>
-            <action class="org.onosproject.cordvtn.cli.OvsdbNodeDeleteCommand"/>
+            <action class="org.onosproject.cordvtn.cli.CordVtnNodeDeleteCommand"/>
         </command>
         <command>
-            <action class="org.onosproject.cordvtn.cli.OvsdbNodeConnectCommand"/>
-        </command>
-        <command>
-            <action class="org.onosproject.cordvtn.cli.OvsdbNodeDisconnectCommand"/>
+            <action class="org.onosproject.cordvtn.cli.CordVtnNodeInitCommand"/>
         </command>
     </command-bundle>
 </blueprint>