CORD-151 add initial skeleton for cord-vtn application

Change-Id: I57bf17445f1e571b51bca2fe7c2631e65cd43145
diff --git a/apps/cordvtn/pom.xml b/apps/cordvtn/pom.xml
index 443fc2c..a019bec 100644
--- a/apps/cordvtn/pom.xml
+++ b/apps/cordvtn/pom.xml
@@ -36,6 +36,19 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-core-serializers</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/ConnectionHandler.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/ConnectionHandler.java
new file mode 100644
index 0000000..af73823
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/ConnectionHandler.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * Entity capable of handling a subject connected and disconnected situation.
+ */
+public interface ConnectionHandler<T> {
+
+    /**
+     * Processes the connected subject.
+     *
+     * @param subject subject
+     */
+    void connected(T subject);
+
+    /**
+     * Processes the disconnected subject.
+     *
+     * @param subject subject.
+     */
+    void disconnected(T subject);
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
new file mode 100644
index 0000000..072254d
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -0,0 +1,311 @@
+/*
+ * 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.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.LeadershipEvent;
+import org.onosproject.cluster.LeadershipEventListener;
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.LogicalClockService;
+import org.onosproject.store.service.StorageService;
+import org.slf4j.Logger;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.cordvtn.OvsdbNode.State.INIT;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * CORD VTN Application that provisions overlay virtual tenant networks.
+ */
+@Component(immediate = true)
+@Service
+public class CordVtn implements CordVtnService {
+
+    protected final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected StorageService storageService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LogicalClockService clockService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ClusterService clusterService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LeadershipService leadershipService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigService configService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigRegistry configRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected HostService hostService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected MastershipService mastershipService;
+
+    private static final int DEFAULT_NUM_THREADS = 1;
+    private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
+            .register(KryoNamespaces.API)
+            .register(OvsdbNode.class);
+
+    private final ExecutorService eventExecutor = Executors.newFixedThreadPool(
+            DEFAULT_NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
+
+    private final LeadershipEventListener leadershipListener = new InternalLeadershipListener();
+    private final DeviceListener deviceListener = new InternalDeviceListener();
+    private final HostListener hostListener = new InternalHostListener();
+    private final NodeHandler nodeHandler = new NodeHandler();
+    private final BridgeHandler bridgeHandler = new BridgeHandler();
+    private final VirtualMachineHandler vmHandler = new VirtualMachineHandler();
+
+    private final ConfigFactory configFactory =
+            new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
+                @Override
+                public CordVtnConfig createConfig() {
+                    return new CordVtnConfig();
+                }
+            };
+
+    private ApplicationId appId;
+    private NodeId local;
+    private EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore;
+    private NodeConnectionManager nodeConnectionManager;
+
+    @Activate
+    protected void activate() {
+        appId = coreService.registerApplication("org.onosproject.cordvtn");
+
+        local = clusterService.getLocalNode().id();
+        nodeStore = storageService.<DeviceId, OvsdbNode>eventuallyConsistentMapBuilder()
+                .withName("cordvtn-nodestore")
+                .withSerializer(NODE_SERIALIZER)
+                .withTimestampProvider((k, v) -> clockService.getTimestamp())
+                .build();
+        configRegistry.registerConfigFactory(configFactory);
+
+        deviceService.addListener(deviceListener);
+        hostService.addListener(hostListener);
+        leadershipService.addListener(leadershipListener);
+        leadershipService.runForLeadership(appId.name());
+        nodeConnectionManager = new NodeConnectionManager(appId, local, nodeStore,
+                                            mastershipService, leadershipService);
+        nodeConnectionManager.start();
+        log.info("Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        nodeConnectionManager.stop();
+        leadershipService.removeListener(leadershipListener);
+        leadershipService.withdraw(appId.name());
+        deviceService.removeListener(deviceListener);
+        hostService.removeListener(hostListener);
+        eventExecutor.shutdown();
+        nodeStore.destroy();
+        configRegistry.unregisterConfigFactory(configFactory);
+        log.info("Stopped");
+    }
+
+    @Override
+    public void addNode(String hostname, IpAddress ip, TpPort port) {
+        DefaultOvsdbNode node = new DefaultOvsdbNode(hostname, ip, port, DeviceId.NONE, INIT);
+
+        if (nodeStore.containsKey(node.deviceId())) {
+            log.warn("Node {} with ovsdb-server {}:{} already exists", hostname, ip, port);
+            return;
+        }
+        nodeStore.put(node.deviceId(), node);
+        log.info("New node {} with ovsdb-server {}:{} has been added", hostname, ip, port);
+    }
+
+    @Override
+    public void deleteNode(IpAddress ip, TpPort port) {
+        DeviceId deviceId = DeviceId.deviceId("ovsdb:" + ip + ":" + port);
+        OvsdbNode node = nodeStore.get(deviceId);
+
+        if (node == null) {
+            log.warn("Node with ovsdb-server on {}:{} does not exist", ip, port);
+            return;
+        }
+        nodeConnectionManager.disconnectNode(node);
+        nodeStore.remove(node.deviceId());
+    }
+
+    @Override
+    public int getNodeCount() {
+        return nodeStore.size();
+    }
+
+    @Override
+    public List<OvsdbNode> getNodes() {
+        return nodeStore.values()
+                .stream()
+                .collect(Collectors.toList());
+    }
+
+    private void initialSetup() {
+        // Read ovsdb nodes from network config
+        CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
+        if (config == null) {
+            log.warn("No configuration found");
+            return;
+        }
+        config.ovsdbNodes().forEach(
+                node -> addNode(node.hostname(), node.ip(), node.port()));
+    }
+
+    private synchronized void processLeadershipChange(NodeId leader) {
+        // Only the leader performs the initial setup
+        if (leader == null || !leader.equals(local)) {
+            return;
+        }
+        initialSetup();
+    }
+
+    private class InternalLeadershipListener implements LeadershipEventListener {
+
+        @Override
+        public void event(LeadershipEvent event) {
+            if (event.subject().topic().equals(appId.name())) {
+                processLeadershipChange(event.subject().leader());
+            }
+        }
+    }
+
+    private class InternalDeviceListener implements DeviceListener {
+
+        @Override
+        public void event(DeviceEvent event) {
+            Device device = event.subject();
+            ConnectionHandler handler =
+                    (device.type() == Device.Type.CONTROLLER ? nodeHandler : bridgeHandler);
+
+            switch (event.type()) {
+                    case DEVICE_ADDED:
+                        eventExecutor.submit(() -> handler.connected(device));
+                        break;
+                    case DEVICE_AVAILABILITY_CHANGED:
+                        eventExecutor.submit(() -> handler.disconnected(device));
+                        break;
+                    default:
+                        break;
+            }
+        }
+    }
+
+    private class InternalHostListener implements HostListener {
+
+        @Override
+        public void event(HostEvent event) {
+            Host vm = event.subject();
+
+            switch (event.type()) {
+                case HOST_ADDED:
+                    eventExecutor.submit(() -> vmHandler.connected(vm));
+                    break;
+                case HOST_REMOVED:
+                    eventExecutor.submit(() -> vmHandler.disconnected(vm));
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    private class NodeHandler implements ConnectionHandler<Device> {
+
+        @Override
+        public void connected(Device device) {
+            // create bridge and set bridgeId
+            // set node state connected
+        }
+
+        @Override
+        public void disconnected(Device device) {
+            // set node state disconnected if the node exists
+            // which means that the node is not deleted explicitly
+        }
+    }
+
+    private class BridgeHandler implements ConnectionHandler<Device> {
+
+        @Override
+        public void connected(Device device) {
+            // create vxlan port
+        }
+
+        @Override
+        public void disconnected(Device device) {
+
+        }
+    }
+
+    private class VirtualMachineHandler implements ConnectionHandler<Host> {
+
+        @Override
+        public void connected(Host host) {
+            // install flow rules for this vm
+        }
+
+        @Override
+        public void disconnected(Host host) {
+            // uninstall flow rules associated with this vm
+        }
+    }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java
new file mode 100644
index 0000000..c2c37ab
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java
@@ -0,0 +1,101 @@
+/*
+ * 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.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Sets;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Configuration object for CORD VTN service.
+ */
+public class CordVtnConfig extends Config<ApplicationId> {
+
+    public static final String OVSDB_NODES = "ovsdbNodes";
+    public static final String HOSTNAME = "hostname";
+    public static final String IP = "ip";
+    public static final String PORT = "port";
+
+    /**
+     * Returns the set of ovsdb nodes read from network config.
+     *
+     * @return set of OvsdbNodeConfig or null
+     */
+    public Set<OvsdbNodeConfig> ovsdbNodes() {
+        Set<OvsdbNodeConfig> ovsdbNodes = Sets.newHashSet();
+
+        JsonNode nodes = object.get(OVSDB_NODES);
+        if (nodes == null) {
+            return null;
+        }
+        nodes.forEach(jsonNode -> ovsdbNodes.add(new OvsdbNodeConfig(
+            jsonNode.path(HOSTNAME).asText(),
+            IpAddress.valueOf(jsonNode.path(IP).asText()),
+            TpPort.tpPort(jsonNode.path(PORT).asInt()))));
+
+        return ovsdbNodes;
+    }
+
+    /**
+     * Configuration for an OVSDB node.
+     */
+    public static class OvsdbNodeConfig {
+
+        private final String hostname;
+        private final IpAddress ip;
+        private final TpPort port;
+
+        public OvsdbNodeConfig(String hostname, IpAddress ip, TpPort port) {
+            this.hostname = checkNotNull(hostname);
+            this.ip = checkNotNull(ip);
+            this.port = checkNotNull(port);
+        }
+
+        /**
+         * Returns hostname of the node.
+         *
+         * @return hostname
+         */
+        public String hostname() {
+            return this.hostname;
+        }
+
+        /**
+         * Returns ip address to access ovsdb-server of the node.
+         *
+         * @return ip address
+         */
+        public IpAddress ip() {
+            return this.ip;
+        }
+
+        /**
+         * Returns port number to access ovsdb-server of the node.
+         *
+         * @return port number
+         */
+        public TpPort port() {
+            return this.port;
+        }
+    }
+}
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 1dee476..d26a10a 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
@@ -15,6 +15,9 @@
  */
 package org.onosproject.cordvtn;
 
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+
 import java.util.List;
 
 /**
@@ -22,19 +25,21 @@
  */
 public interface CordVtnService {
     /**
-     * Adds new nodes to the service and processes initial setup.
+     * Adds a new node to the service.
      *
-     * @param ovsdbNodes list of nodes
+     * @param hostname hostname of the node
+     * @param ip ip address to access the ovsdb server running on the node
+     * @param port port number to access the ovsdb server running on the node
      */
-    void addNodes(List<OvsdbNode> ovsdbNodes);
+    void addNode(String hostname, IpAddress ip, TpPort port);
 
     /**
-     * Deletes the nodes from the service and cleans up unnecessary configurations
-     * associated with the deleted nodes.
+     * Deletes the node from the service.
      *
-     * @param ovsdbNodes list of nodes
+     * @param ip ip address to access the ovsdb server running on the node
+     * @param port port number to access the ovsdb server running on the node
      */
-    void deleteNodes(List<OvsdbNode> ovsdbNodes);
+    void deleteNode(IpAddress ip, TpPort port);
 
     /**
      * Returns the number of the nodes known to the service.
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
new file mode 100644
index 0000000..b8cdbe9
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
@@ -0,0 +1,97 @@
+/*
+ * 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.Objects;
+
+/**
+ * OvsdbNode implementation.
+ */
+public class DefaultOvsdbNode implements OvsdbNode {
+
+    private final String hostname;
+    private final IpAddress ip;
+    private final TpPort port;
+    private final DeviceId deviceId;
+    private final DeviceId bridgeId;
+    private final State state;
+
+    public DefaultOvsdbNode(String hostname, IpAddress ip, TpPort port,
+                            DeviceId bridgeId, State state) {
+        this.hostname = hostname;
+        this.ip = ip;
+        this.port = port;
+        this.deviceId = DeviceId.deviceId(
+                "ovsdb:" + ip.toString() + ":" + port.toString());
+        this.bridgeId = bridgeId;
+        this.state = state;
+    }
+
+    @Override
+    public IpAddress ip() {
+        return this.ip;
+    }
+
+    @Override
+    public TpPort port() {
+        return this.port;
+    }
+
+    @Override
+    public String hostname() {
+        return this.hostname;
+    }
+
+    @Override
+    public State state() {
+        return this.state;
+    }
+
+    @Override
+    public DeviceId deviceId() {
+        return this.deviceId;
+    }
+
+    @Override
+    public DeviceId bridgeId() {
+        return this.bridgeId;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o instanceof DefaultOvsdbNode) {
+            DefaultOvsdbNode that = (DefaultOvsdbNode) o;
+            // We compare the ip and port only.
+            if (this.ip.equals(that.ip) && this.port.equals(that.port)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ip, port);
+    }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/NodeConnectionManager.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/NodeConnectionManager.java
new file mode 100644
index 0000000..0b7029e
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/NodeConnectionManager.java
@@ -0,0 +1,145 @@
+/*
+ * 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.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.slf4j.Logger;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import static org.onlab.util.Tools.groupedThreads;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Node connection manager.
+ */
+public class NodeConnectionManager {
+    protected final Logger log = getLogger(getClass());
+
+    private final ApplicationId appId;
+    private final NodeId localId;
+    private final EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore;
+    private final MastershipService mastershipService;
+    private final LeadershipService leadershipService;
+
+    private static final int DELAY_SEC = 5;
+    private ScheduledExecutorService connectionExecutor;
+
+    /**
+     * Creates a new NodeConnectionManager.
+     *
+     * @param localId local id
+     * @param nodeStore node store
+     * @param mastershipService mastership service
+     */
+    public NodeConnectionManager(ApplicationId appId, NodeId localId,
+                                 EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore,
+                                 MastershipService mastershipService,
+                                 LeadershipService leadershipService) {
+        this.appId = appId;
+        this.localId = localId;
+        this.nodeStore = nodeStore;
+        this.mastershipService = mastershipService;
+        this.leadershipService = leadershipService;
+    }
+
+    /**
+     * Starts the node connection manager.
+     */
+    public void start() {
+        connectionExecutor = Executors.newSingleThreadScheduledExecutor(
+                        groupedThreads("onos/cordvtn", "connection-executor"));
+        connectionExecutor.scheduleWithFixedDelay(() -> nodeStore.values()
+                .stream()
+                .filter(node -> localId.equals(getMaster(node)))
+                .forEach(node -> connectNode(node)), 0, DELAY_SEC, TimeUnit.SECONDS);
+    }
+
+    /**
+     * Stops the node connection manager.
+     */
+    public void stop() {
+        connectionExecutor.shutdown();
+    }
+
+    /**
+     * Adds a new node to the system.
+     *
+     * @param ovsdbNode ovsdb node
+     */
+    public void connectNode(OvsdbNode ovsdbNode) {
+        switch (ovsdbNode.state()) {
+            case INIT:
+            case DISCONNECTED:
+                // TODO: set the node to passive mode
+            case READY:
+                // TODO: initiate connection
+                break;
+            case CONNECTED:
+                break;
+            default:
+        }
+    }
+
+    /**
+     * Deletes the ovsdb node.
+     *
+     * @param ovsdbNode ovsdb node
+     */
+    public void disconnectNode(OvsdbNode ovsdbNode) {
+        switch (ovsdbNode.state()) {
+            case CONNECTED:
+                // TODO: disconnect
+                break;
+            case INIT:
+            case READY:
+            case DISCONNECTED:
+                break;
+            default:
+        }
+    }
+
+    private NodeId getMaster(OvsdbNode ovsdbNode) {
+        // Return the master of the bridge(switch) if it exist or
+        // return the current leader
+        if (ovsdbNode.bridgeId() == DeviceId.NONE) {
+            return leadershipService.getLeader(this.appId.name());
+        } else {
+            return mastershipService.getMasterFor(ovsdbNode.bridgeId());
+        }
+    }
+
+    private void setPassiveMode(OvsdbNode ovsdbNode) {
+        // TODO: need ovsdb client implementation first
+        // TODO: set the remove ovsdb server passive mode
+        // TODO: set the node state READY if it succeed
+    }
+
+    private void connect(OvsdbNode ovsdbNode) {
+        // TODO: need ovsdb client implementation first
+    }
+
+    private void disconnect(OvsdbNode ovsdbNode) {
+        // TODO: need ovsdb client implementation first
+    }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
index 75e61d7..bb2a0b7 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
@@ -18,8 +18,6 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.TpPort;
 import org.onosproject.net.DeviceId;
-import org.onosproject.net.behaviour.BridgeConfig;
-import org.onosproject.net.behaviour.TunnelConfig;
 
 /**
  * Representation of a node with ovsdb server.
@@ -29,7 +27,7 @@
      * State of the ovsdb node.
      */
     enum State {
-        READY, CONNECTED, DISCONNECTED
+        INIT, READY, CONNECTED, DISCONNECTED
     }
 
     /**
@@ -47,44 +45,30 @@
     TpPort port();
 
     /**
+     * Returns the hostname of the node.
+     *
+     * @return hostname
+     */
+    String hostname();
+
+    /**
      * Returns the state of the node.
      *
      * @return state of the node
      */
-    State getState();
-
-    /**
-     * Sets the state of the node.
-     *
-     * @param state state of the node
-     */
-    void setState(State state);
+    State state();
 
     /**
      * Returns the device ID of the node.
      *
      * @return device id
      */
-    DeviceId getDeviceId();
+    DeviceId deviceId();
 
     /**
-     * Sets the device id of the node.
+     * Returns the device ID of the bridge associated with this node.
      *
-     * @param deviceId device identifier
+     * @return device id
      */
-    void setDeviceId(DeviceId deviceId);
-
-    /**
-     * Returns the bridge configuration handler of the node.
-     *
-     * @return bridge config behavior instance
-     */
-    BridgeConfig getBridgeConfig();
-
-    /**
-     * Returns the tunnel configuration handler of the node.
-     *
-     * @return tunnel config behavior instance
-     */
-    TunnelConfig getTunnelConfig();
+    DeviceId bridgeId();
 }