CORD-1071 Refactor VTN node service

Done
- Separated interface, implementation and store for node management
- Added unit tests for node manager and handler
- Offloaded more of the event handling off of the Atomix event thread

Todo
- Add REST interface for the node service

Change-Id: Ibf90d3a621013497cc891ca3086db6648f5d49df
diff --git a/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
index bb4ce5e..69ecbe6 100644
--- a/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
+++ b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
@@ -28,12 +28,14 @@
 import org.onlab.packet.TpPort;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.behaviour.ControllerInfo;
 import org.onosproject.net.config.Config;
 import org.onosproject.net.config.InvalidFieldException;
 import org.opencord.cordvtn.api.net.CidrAddr;
 import org.opencord.cordvtn.api.node.CordVtnNode;
 import org.opencord.cordvtn.api.node.SshAccessInfo;
+import org.opencord.cordvtn.impl.DefaultCordVtnNode;
 import org.slf4j.Logger;
 
 import java.util.List;
@@ -196,31 +198,31 @@
         String ovsdbPort = getConfig(object, OVSDB_PORT);
 
         object.get(CORDVTN_NODES).forEach(vtnNode -> {
-            CidrAddr localMgmt = CidrAddr.valueOf(get(LOCAL_MANAGEMENT_IP, ""));
-            CidrAddr hostsMgmt = CidrAddr.valueOf(getConfig(vtnNode, HOST_MANAGEMENT_IP));
+            CidrAddr localMgmtIp = CidrAddr.valueOf(get(LOCAL_MANAGEMENT_IP, ""));
+            CidrAddr hostsMgmtIp = CidrAddr.valueOf(getConfig(vtnNode, HOST_MANAGEMENT_IP));
 
             SshAccessInfo sshInfo = new SshAccessInfo(
-                    hostsMgmt.ip().getIp4Address(),
+                    hostsMgmtIp.ip().getIp4Address(),
                     TpPort.tpPort(Integer.parseInt(getConfig(sshNode, SSH_PORT))),
                     getConfig(sshNode, SSH_USER),
                     getConfig(sshNode, SSH_KEY_FILE));
 
-            CordVtnNode.Builder nodeBuilder = CordVtnNode.builder()
+            CordVtnNode.Builder nodeBuilder = DefaultCordVtnNode.builder()
                     .hostname(getConfig(vtnNode, HOSTNAME))
-                    .hostMgmtIp(hostsMgmt)
-                    .localMgmtIp(localMgmt)
-                    .dataIp(getConfig(vtnNode, DATA_IP))
+                    .hostManagementIp(hostsMgmtIp)
+                    .localManagementIp(localMgmtIp)
+                    .dataIp(CidrAddr.valueOf(getConfig(vtnNode, DATA_IP)))
                     .sshInfo(sshInfo)
-                    .integrationBridgeId(getConfig(vtnNode, INTEGRATION_BRIDGE_ID))
-                    .dataIface(getConfig(vtnNode, DATA_IFACE));
+                    .integrationBridgeId(DeviceId.deviceId(getConfig(vtnNode, INTEGRATION_BRIDGE_ID)))
+                    .dataInterface(getConfig(vtnNode, DATA_IFACE));
 
             if (!Strings.isNullOrEmpty(ovsdbPort)) {
-                nodeBuilder.ovsdbPort(Integer.parseInt(ovsdbPort));
+                nodeBuilder.ovsdbPort(TpPort.tpPort(Integer.parseInt(ovsdbPort)));
             }
 
             String hostMgmtIface = getConfig(vtnNode, HOST_MANAGEMENT_IFACE);
             if (!Strings.isNullOrEmpty(hostMgmtIface)) {
-                nodeBuilder.hostMgmtIface(hostMgmtIface);
+                nodeBuilder.hostManagementInterface(hostMgmtIface);
             }
 
             nodes.add(nodeBuilder.build());
diff --git a/src/main/java/org/opencord/cordvtn/api/core/CordVtnPipeline.java b/src/main/java/org/opencord/cordvtn/api/core/CordVtnPipeline.java
new file mode 100644
index 0000000..278492a
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/core/CordVtnPipeline.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.core;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.flow.FlowRule;
+import org.opencord.cordvtn.api.node.CordVtnNode;
+
+/**
+ * Service providing cordvtn pipeline.
+ */
+public interface CordVtnPipeline {
+
+    // tables
+    int TABLE_ZERO = 0;
+    int TABLE_IN_PORT = 1;
+    int TABLE_ACCESS = 2;
+    int TABLE_IN_SERVICE = 3;
+    int TABLE_DST = 4;
+    int TABLE_TUNNEL_IN = 5;
+    int TABLE_VLAN = 6;
+
+    // priorities
+    int PRIORITY_MANAGEMENT = 55000;
+    int PRIORITY_HIGH = 50000;
+    int PRIORITY_DEFAULT = 5000;
+    int PRIORITY_LOW = 4000;
+    int PRIORITY_ZERO = 0;
+
+    VlanId VLAN_WAN = VlanId.vlanId((short) 500);
+
+    /**
+     * Initializes the pipeline for the supplied node.
+     *
+     * @param node cordvtn node
+     */
+    void initPipeline(CordVtnNode node);
+
+    /**
+     * Clean up the pipeline for all nodes.
+     */
+    void cleanupPipeline();
+
+    /**
+     * Processes the given flow rule.
+     *
+     * @param install install or remove
+     * @param rule    flow rule to process
+     */
+    void processFlowRule(boolean install, FlowRule rule);
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/ConnectionHandler.java b/src/main/java/org/opencord/cordvtn/api/node/ConnectionHandler.java
deleted file mode 100644
index f3e3ad4..0000000
--- a/src/main/java/org/opencord/cordvtn/api/node/ConnectionHandler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.opencord.cordvtn.api.node;
-
-/**
- * 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/src/main/java/org/opencord/cordvtn/api/node/CordVtnNode.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNode.java
index 153eed3..1e873a4 100644
--- a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNode.java
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNode.java
@@ -15,489 +15,193 @@
  */
 package org.opencord.cordvtn.api.node;
 
-import com.google.common.base.MoreObjects;
-import com.google.common.base.Strings;
-import com.google.common.collect.Sets;
 import org.onlab.packet.TpPort;
 import org.onosproject.net.DeviceId;
 import org.opencord.cordvtn.api.net.CidrAddr;
 
-import java.util.Comparator;
-import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.opencord.cordvtn.api.Constants.DEFAULT_OVSDB_PORT;
-import static org.opencord.cordvtn.api.Constants.DEFAULT_TUNNEL;
-
 /**
- * Representation of a compute infrastructure node for CORD VTN service.
+ * Representation of a compute node for service instance provisioning.
  */
-public final class CordVtnNode {
-
-    private final String hostname;
-    private final CidrAddr hostMgmtIp;
-    private final CidrAddr localMgmtIp;
-    private final CidrAddr dataIp;
-    private final Optional<TpPort> ovsdbPort;
-    private final SshAccessInfo sshInfo;
-    private final DeviceId integrationBridgeId;
-    private final String dataIface;
-    private final Optional<String> hostMgmtIface;
-    private final CordVtnNodeState state;
-
-    public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR =
-            (node1, node2) -> node1.hostname().compareTo(node2.hostname());
+public interface CordVtnNode {
 
     /**
-     * Creates a new node.
-     *
-     * @param hostname hostname
-     * @param hostMgmtIp host management network address
-     * @param localMgmtIp local management network address
-     * @param dataIp data network address
-     * @param ovsdbPort port number for ovsdb connection
-     * @param sshInfo ssh access information
-     * @param integrationBridgeId integration bridge identifier
-     * @param dataIface data plane interface name
-     * @param hostMgmtIface host management network interface
-     * @param state cordvtn node state
-     */
-    private CordVtnNode(String hostname,
-                        CidrAddr hostMgmtIp,
-                        CidrAddr localMgmtIp,
-                        CidrAddr dataIp,
-                        Optional<TpPort> ovsdbPort,
-                        SshAccessInfo sshInfo,
-                        DeviceId integrationBridgeId,
-                        String dataIface,
-                        Optional<String> hostMgmtIface,
-                        CordVtnNodeState state) {
-        this.hostname = hostname;
-        this.hostMgmtIp = hostMgmtIp;
-        this.localMgmtIp = localMgmtIp;
-        this.dataIp = dataIp;
-        this.ovsdbPort = ovsdbPort;
-        this.sshInfo = sshInfo;
-        this.integrationBridgeId = integrationBridgeId;
-        this.dataIface = dataIface;
-        this.hostMgmtIface = hostMgmtIface;
-        this.state = state;
-    }
-
-    /**
-     * Returns cordvtn node with new state.
-     *
-     * @param node cordvtn node
-     * @param state cordvtn node init state
-     * @return cordvtn node
-     */
-    public static CordVtnNode getUpdatedNode(CordVtnNode node, CordVtnNodeState state) {
-        return new CordVtnNode(node.hostname,
-                               node.hostMgmtIp, node.localMgmtIp, node.dataIp,
-                               node.ovsdbPort,
-                               node.sshInfo,
-                               node.integrationBridgeId,
-                               node.dataIface, node.hostMgmtIface,
-                               state);
-    }
-
-    /**
-     * Returns the hostname.
+     * Returns the hostname of the node.
      *
      * @return hostname
      */
-    public String hostname() {
-        return this.hostname;
-    }
+    String hostname();
 
     /**
-     * Returns the host management network address.
+     * Returns the host management IP address of the node.
      *
-     * @return network address
+     * @return ip address with cidr notation
      */
-    public CidrAddr hostMgmtIp() {
-        return this.hostMgmtIp;
-    }
+    CidrAddr hostManagementIp();
 
     /**
-     * Returns the local management network address.
+     * Returns the local management IP address of the node.
      *
-     * @return network address
+     * @return ip address with the cidr notation
      */
-    public CidrAddr localMgmtIp() {
-        return this.localMgmtIp;
-    }
+    // TODO remove this after dynamic provisioning of local management network
+    CidrAddr localManagementIp();
 
     /**
-     * Returns the data network address.
+     * Returns the data network IP address of the node.
      *
-     * @return network address
+     * @return ip address with the cidr notation
      */
-    public CidrAddr dataIp() {
-        return this.dataIp;
-    }
+    CidrAddr dataIp();
 
     /**
-     * Returns the port number used for OVSDB connection.
-     * It returns default OVSDB port 6640, if it's not specified.
+     * Returns the integration bridge device identifier.
      *
-     * @return port number
+     * @return device id
      */
-    public TpPort ovsdbPort() {
-        if (this.ovsdbPort.isPresent()) {
-            return this.ovsdbPort.get();
-        } else {
-            return TpPort.tpPort(DEFAULT_OVSDB_PORT);
-        }
-    }
+    DeviceId integrationBridgeId();
+
+    /**
+     * Returns the data network interface name.
+     *
+     * @return interface name
+     */
+    String dataInterface();
+
+    /**
+     * Returns host management network interface name.
+     *
+     * @return interface name; null if not set
+     */
+    String hostManagementInterface();
+
+    /**
+     * Returns the port number of the OVSDB server.
+     *
+     * @return port number; 6640 if not set
+     */
+    TpPort ovsdbPort();
 
     /**
      * Returns the SSH access information.
      *
      * @return ssh access information
      */
-    public SshAccessInfo sshInfo() {
-        return this.sshInfo;
-    }
-
-    /**
-     * Returns the identifier of the integration bridge.
-     *
-     * @return device id
-     */
-    public DeviceId integrationBridgeId() {
-        return this.integrationBridgeId;
-    }
-
-    /**
-     * Returns the identifier of the OVSDB device.
-     *
-     * @return device id
-     */
-    public DeviceId ovsdbId() {
-        return DeviceId.deviceId("ovsdb:" + this.hostMgmtIp.ip().toString());
-    }
-
-    /**
-     * Returns data network interface name.
-     *
-     * @return data network interface name
-     */
-    public String dataIface() {
-        return this.dataIface;
-    }
-
-    /**
-     * Returns host management network interface name.
-     *
-     * @return host management network interface name
-     */
-    public Optional<String> hostMgmtIface() {
-        return this.hostMgmtIface;
-    }
-
-    /**
-     * Returns a set of network interfaces for the VTN service to work properly.
-     *
-     * @return set of interface names
-     */
-    public Set<String> systemIfaces() {
-        Set<String> ifaces = Sets.newHashSet(DEFAULT_TUNNEL, dataIface);
-        if (hostMgmtIface.isPresent()) {
-            ifaces.add(hostMgmtIface.get());
-        }
-        return ifaces;
-    }
+    SshAccessInfo sshInfo();
 
     /**
      * Returns the state of the node.
      *
      * @return state
      */
-    public CordVtnNodeState state() {
-        return this.state;
-    }
-
-    @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(hostMgmtIp, that.hostMgmtIp) &&
-                    Objects.equals(localMgmtIp, that.localMgmtIp) &&
-                    Objects.equals(dataIp, that.dataIp) &&
-                    Objects.equals(ovsdbPort, that.ovsdbPort) &&
-                    Objects.equals(sshInfo, that.sshInfo) &&
-                    Objects.equals(integrationBridgeId, that.integrationBridgeId) &&
-                    Objects.equals(dataIface, that.dataIface) &&
-                    Objects.equals(hostMgmtIface, that.hostMgmtIface)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(hostname,
-                            hostMgmtIp,
-                            localMgmtIp,
-                            dataIp,
-                            ovsdbPort,
-                            sshInfo,
-                            integrationBridgeId,
-                            dataIface,
-                            hostMgmtIface);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .add("hostname", hostname)
-                .add("hostMgmtIp", hostMgmtIp)
-                .add("localMgmtIp", localMgmtIp)
-                .add("dataIp", dataIp)
-                .add("port", ovsdbPort)
-                .add("sshInfo", sshInfo)
-                .add("integrationBridgeId", integrationBridgeId)
-                .add("dataIface", dataIface)
-                .add("hostMgmtIface", hostMgmtIface)
-                .add("state", state)
-                .toString();
-    }
+    CordVtnNodeState state();
 
     /**
-     * Returns new node builder instance.
+     * Returns the identifier of the OVSDB device.
      *
-     * @return cordvtn node builder
+     * @return device id
      */
-    public static Builder builder() {
-        return new Builder();
-    }
+    DeviceId ovsdbId();
 
     /**
-     * Builder of node entities.
+     * Returns system interfaces of the node.
+     *
+     * @return set of interface names
      */
-    public static final class Builder {
-        private String hostname;
-        private CidrAddr hostMgmtIp;
-        private CidrAddr localMgmtIp;
-        private CidrAddr dataIp;
-        private Optional<TpPort> ovsdbPort =
-                Optional.of(TpPort.tpPort(DEFAULT_OVSDB_PORT));
-        private SshAccessInfo sshInfo;
-        private DeviceId integrationBridgeId;
-        private String dataIface;
-        private Optional<String> hostMgmtIface = Optional.empty();
-        private CordVtnNodeState state = CordVtnNodeState.noState();
+    Set<String> systemInterfaces();
 
-        private Builder() {
-        }
+    /**
+     * Builder of cordvtn node entities.
+     */
+    interface Builder {
 
         /**
-         * Builds an immutable cordvtn node.
+         * Returns new cordvtn node.
          *
          * @return cordvtn node
          */
-        public CordVtnNode build() {
-            // validate attributes
-            checkArgument(!Strings.isNullOrEmpty(hostname));
-            checkNotNull(hostMgmtIp);
-            checkNotNull(localMgmtIp);
-            checkNotNull(dataIp);
-            checkNotNull(ovsdbPort);
-            checkNotNull(sshInfo);
-            checkNotNull(integrationBridgeId);
-            checkNotNull(dataIface);
-            checkNotNull(hostMgmtIface);
-            return new CordVtnNode(hostname,
-                                   hostMgmtIp, localMgmtIp, dataIp,
-                                   ovsdbPort,
-                                   sshInfo,
-                                   integrationBridgeId,
-                                   dataIface,
-                                   hostMgmtIface,
-                                   state);
-        }
+        CordVtnNode build();
 
         /**
-         * Returns cordvtn node builder with hostname.
+         * Returns cordvtn node builder with the supplied hostname.
          *
-         * @param hostname hostname
+         * @param hostname hostname of the node
          * @return cordvtn node builder
          */
-        public Builder hostname(String hostname) {
-            checkArgument(!Strings.isNullOrEmpty(hostname));
-            this.hostname = hostname;
-            return this;
-        }
+        Builder hostname(String hostname);
 
         /**
-         * Returns cordvtn node builder with host management network IP address.
+         * Returns cordvtn node builder with the supplied host management IP.
          *
-         * @param hostMgmtIp host management netework ip address
+         * @param hostMgmtIp ip address with cidr notation
          * @return cordvtn node builder
          */
-        public Builder hostMgmtIp(CidrAddr hostMgmtIp) {
-            checkNotNull(hostMgmtIp);
-            this.hostMgmtIp = hostMgmtIp;
-            return this;
-        }
+        Builder hostManagementIp(CidrAddr hostMgmtIp);
 
         /**
-         * Returns cordvtn node builder with host management network IP address.
+         * Returns cordvtn node builder with the supplied local management IP.
          *
-         * @param cidr string value of the host management network ip address
+         * @param localMgmtIp ip address with cidr notation
          * @return cordvtn node builder
          */
-        public Builder hostMgmtIp(String cidr) {
-            this.hostMgmtIp = CidrAddr.valueOf(cidr);
-            return this;
-        }
+        // TODO remove this after dynamic provisioning of local management network
+        Builder localManagementIp(CidrAddr localMgmtIp);
 
         /**
-         * Returns cordvtn node builder with local management network IP address.
+         * Returns cordvtn node builder with the supplied data IP.
          *
-         * @param localMgmtIp local management network ip address
+         * @param dataIp ip address with cidr notation
          * @return cordvtn node builder
          */
-        public Builder localMgmtIp(CidrAddr localMgmtIp) {
-            checkNotNull(localMgmtIp);
-            this.localMgmtIp = localMgmtIp;
-            return this;
-        }
+        Builder dataIp(CidrAddr dataIp);
 
         /**
-         * Returns cordvtn node builder with local management netework IP address.
+         * Returns cordvtn node builder with the supplied integration bridge identifier.
          *
-         * @param cidr string value of the local management network ip address
+         * @param bridgeId bridge identifier
          * @return cordvtn node builder
          */
-        public Builder localMgmtIp(String cidr) {
-            this.localMgmtIp = CidrAddr.valueOf(cidr);
-            return this;
-        }
+        Builder integrationBridgeId(DeviceId bridgeId);
 
         /**
-         * Returns cordvtn node builder with data network IP address.
+         * Returns cordvtn node builder with the supplied data interface.
          *
-         * @param dataIp data network ip address
+         * @param dataIface interface name
          * @return cordvtn node builder
          */
-        public Builder dataIp(CidrAddr dataIp) {
-            checkNotNull(dataIp);
-            this.dataIp = dataIp;
-            return this;
-        }
+        Builder dataInterface(String dataIface);
 
         /**
-         * Returns cordvtn node builder with data network IP address.
+         * Returns cordvtn node builder with the supplied host management interface.
          *
-         * @param cidr string value of the data network ip address
+         * @param hostMgmtIface interface name
          * @return cordvtn node builder
          */
-        public Builder dataIp(String cidr) {
-            this.dataIp = CidrAddr.valueOf(cidr);
-            return this;
-        }
+        Builder hostManagementInterface(String hostMgmtIface);
 
         /**
-         * Returns cordvtn node builder with OVSDB server listen port number.
+         * Returns cordvtn node builder with the supplied OVSDB port.
          *
-         * @param port ovsdb server listen port number
+         * @param ovsdbPort transport layer port number
          * @return cordvtn node builder
          */
-        public Builder ovsdbPort(TpPort port) {
-            checkNotNull(port);
-            this.ovsdbPort = Optional.of(port);
-            return this;
-        }
+        Builder ovsdbPort(TpPort ovsdbPort);
 
         /**
-         * Returns cordvtn node builder with OVSDB server listen port number.
+         * Returns cordvtn node builder with the supplied SSH access information.
          *
-         * @param port int value of the ovsdb server listen port number
-         * @return cordvtn node builder
-         */
-        public Builder ovsdbPort(int port) {
-            this.ovsdbPort = Optional.of(TpPort.tpPort(port));
-            return this;
-        }
-
-        /**
-         * Returns cordvtn node builder with SSH access information.
          * @param sshInfo ssh access information
          * @return cordvtn node builder
          */
-        public Builder sshInfo(SshAccessInfo sshInfo) {
-            checkNotNull(sshInfo);
-            this.sshInfo = sshInfo;
-            return this;
-        }
+        Builder sshInfo(SshAccessInfo sshInfo);
 
         /**
-         * Returns cordvtn node builder with integration bridge ID.
+         * Returns cordvtn node builder with the supplied initialize state.
          *
-         * @param deviceId device id of the integration bridge
+         * @param state cordvtn node state
          * @return cordvtn node builder
          */
-        public Builder integrationBridgeId(DeviceId deviceId) {
-            checkNotNull(deviceId);
-            this.integrationBridgeId = deviceId;
-            return this;
-        }
-
-        /**
-         * Returns cordvtn node builder with integration bridge ID.
-         *
-         * @param deviceId string value of the integration bridge device id
-         * @return cordvtn node builder
-         */
-        public Builder integrationBridgeId(String deviceId) {
-            this.integrationBridgeId = DeviceId.deviceId(deviceId);
-            return this;
-        }
-
-        /**
-         * Returns cordvtn node builder with data network interface name.
-         *
-         * @param dataIface data network interface name
-         * @return cordvtn node builder
-         */
-        public Builder dataIface(String dataIface) {
-            checkArgument(!Strings.isNullOrEmpty(dataIface));
-            this.dataIface = dataIface;
-            return this;
-        }
-
-        /**
-         * Returns cordvtn node builder with host management network interface.
-         *
-         * @param hostMgmtIface host management network interface name
-         * @return cordvtn node builder
-         */
-        public Builder hostMgmtIface(String hostMgmtIface) {
-            this.hostMgmtIface = Optional.ofNullable(hostMgmtIface);
-            return this;
-        }
-
-        /**
-         * Returns cordvtn node builder with init state.
-         *
-         * @param state init state
-         * @return cordvtn node builder
-         */
-        public Builder state(CordVtnNodeState state) {
-            checkNotNull(state);
-            this.state = state;
-            return this;
-        }
+        Builder state(CordVtnNodeState state);
     }
 }
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeAdminService.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeAdminService.java
new file mode 100644
index 0000000..b312185
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeAdminService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+/**
+ * Service for administering the inventory of {@link CordVtnNode}.
+ */
+public interface CordVtnNodeAdminService {
+
+    /**
+     * Creates a new node.
+     *
+     * @param node cordvtn node
+     */
+    void createNode(CordVtnNode node);
+
+    /**
+     * Updates the node.
+     *
+     * @param node cordvtn node
+     */
+    void updateNode(CordVtnNode node);
+
+    /**
+     * Removes the node with the supplied hostname.
+     *
+     * @param hostname hostname of the node
+     * @return removed node; null if it fails
+     */
+    CordVtnNode removeNode(String hostname);
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeEvent.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeEvent.java
new file mode 100644
index 0000000..3b6651f
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeEvent.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes cordvtn node events.
+ */
+public class CordVtnNodeEvent extends AbstractEvent<CordVtnNodeEvent.Type, CordVtnNode> {
+
+    public enum Type {
+
+        /**
+         * Signifies that the new node is created.
+         */
+        NODE_CREATED,
+
+        /**
+         * Signifies that the node is updated.
+         */
+        NODE_UPDATED,
+
+        /**
+         * Signifies that the node is removed.
+         */
+        NODE_REMOVED,
+
+        /**
+         * Signifies that the node state is changed to complete.
+         */
+        NODE_COMPLETE,
+
+        /**
+         * Signifies that the node state is changed to incomplete.
+         */
+        NODE_INCOMPLETE
+    }
+
+    /**
+     * Creates an event of a given type and the specified node.
+     *
+     * @param type cordvtn node event type
+     * @param node cordvtn node subject
+     */
+    public CordVtnNodeEvent(Type type, CordVtnNode node) {
+        super(type, node);
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeHandler.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeHandler.java
new file mode 100644
index 0000000..7dc1eb2
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeHandler.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+/**
+ * Service providing cordvtn node bootstrapping.
+ */
+public interface CordVtnNodeHandler {
+
+    /**
+     * Processes the init state node.
+     *
+     * @param node cordvtn node
+     */
+    void processInitState(CordVtnNode node);
+
+    /**
+     * Processes the device created state node.
+     *
+     * @param node cordvtn node
+     */
+    void processDeviceCreatedState(CordVtnNode node);
+
+    /**
+     * Processes the port created state node.
+     *
+     * @param node cordvtn node
+     */
+    void processPortCreatedState(CordVtnNode node);
+
+    /**
+     * Processes the complete state node.
+     *
+     * @param node cordvtn node
+     */
+    void processCompleteState(CordVtnNode node);
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeListener.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeListener.java
new file mode 100644
index 0000000..91bd7ed
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Listener for cordvtn node event.
+ */
+public interface CordVtnNodeListener extends EventListener<CordVtnNodeEvent> {
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeService.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeService.java
new file mode 100644
index 0000000..afa9b17
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.DeviceId;
+
+import java.util.Set;
+
+/**
+ * Service for interfacing with the inventory of {@link CordVtnNode}.
+ */
+public interface CordVtnNodeService extends ListenerService<CordVtnNodeEvent, CordVtnNodeListener> {
+
+    /**
+     * Returns all nodes.
+     *
+     * @return set of nodes; empty set if no node presents
+     */
+    Set<CordVtnNode> nodes();
+
+    /**
+     * Returns nodes in complete state.
+     *
+     * @return set of nodes; empty set if no complete node presents
+     */
+    Set<CordVtnNode> completeNodes();
+
+    /**
+     * Returns the node with the given hostname.
+     *
+     * @param hostname hostname of the node
+     * @return cordvtn node; null if no node present with the hostname
+     */
+    CordVtnNode node(String hostname);
+
+    /**
+     * Returns the node with the given integration bridge device identifier.
+     *
+     * @param deviceId integration bridge device id
+     * @return cordvtn node; null if no node present with the device id
+     */
+    CordVtnNode node(DeviceId deviceId);
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeState.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeState.java
index e3d9cd5..49e02ff 100644
--- a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeState.java
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeState.java
@@ -18,13 +18,64 @@
 /**
  * Entity that defines possible init state of the cordvtn node.
  */
-public interface CordVtnNodeState {
+public enum CordVtnNodeState {
+
+    INIT {
+        @Override
+        public void process(CordVtnNodeHandler handler, CordVtnNode node) {
+            handler.processInitState(node);
+        }
+
+        @Override
+        public CordVtnNodeState nextState() {
+            return DEVICE_CREATED;
+        }
+    },
+    DEVICE_CREATED {
+        @Override
+        public void process(CordVtnNodeHandler handler, CordVtnNode node) {
+            handler.processDeviceCreatedState(node);
+        }
+
+        @Override
+        public CordVtnNodeState nextState() {
+            return PORT_CREATED;
+        }
+    },
+    PORT_CREATED {
+        @Override
+        public void process(CordVtnNodeHandler handler, CordVtnNode node) {
+            handler.processPortCreatedState(node);
+        }
+
+        @Override
+        public CordVtnNodeState nextState() {
+            return COMPLETE;
+        }
+    },
+    COMPLETE {
+        @Override
+        public void process(CordVtnNodeHandler handler, CordVtnNode node) {
+            handler.processCompleteState(node);
+        }
+
+        @Override
+        public CordVtnNodeState nextState() {
+            // last state
+            return COMPLETE;
+        }
+    };
+
     /**
-     * Returns null for no state.
+     * Processes the current node state to proceed to the next state.
      *
-     * @return null
+     * @param handler cordvtn node state handler
+     * @param node    cordvtn node
      */
-    static CordVtnNodeState noState() {
-        return null;
-    }
+    public abstract void process(CordVtnNodeHandler handler, CordVtnNode node);
+
+    /**
+     * Returns the next node state.
+     */
+    public abstract CordVtnNodeState nextState();
 }
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeStore.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeStore.java
new file mode 100644
index 0000000..d4626d5
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeStore.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Manages the inventory of cordvtn nodes; not intended for direct use.
+ */
+public interface CordVtnNodeStore extends Store<CordVtnNodeEvent, CordVtnNodeStoreDelegate> {
+
+    /**
+     * Returns all nodes.
+     *
+     * @return set of nodes; empty set if no node presents
+     */
+    Set<CordVtnNode> nodes();
+
+    /**
+     * Returns the node with the given hostname.
+     *
+     * @param hostname hostname of the node
+     * @return cordvtn node; null if no node present with the hostname
+     */
+    CordVtnNode node(String hostname);
+
+    /**
+     * Creates a new node.
+     *
+     * @param node cordvtn node
+     */
+    void createNode(CordVtnNode node);
+
+    /**
+     * Updates the node.
+     *
+     * @param node cordvtn node
+     */
+    void updateNode(CordVtnNode node);
+
+    /**
+     * Removes the node with the supplied hostname.
+     *
+     * @param hostname hostname of the node
+     * @return removed node; null if it failed
+     */
+    CordVtnNode removeNode(String hostname);
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeStoreDelegate.java b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeStoreDelegate.java
new file mode 100644
index 0000000..366dea5
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/CordVtnNodeStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * CordVtn Node store delegate.
+ */
+public interface CordVtnNodeStoreDelegate extends StoreDelegate<CordVtnNodeEvent> {
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/node/DeviceHandler.java b/src/main/java/org/opencord/cordvtn/api/node/DeviceHandler.java
new file mode 100644
index 0000000..b6e49c1
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/node/DeviceHandler.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api.node;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+
+/**
+ * Entity capable of handling a device state updates.
+ */
+public interface DeviceHandler {
+
+    /**
+     * Processes the connected device.
+     *
+     * @param device device
+     */
+    void connected(Device device);
+
+    /**
+     * Processes the disconnected device.
+     *
+     * @param device device.
+     */
+    void disconnected(Device device);
+
+    /**
+     * Processes newly added port.
+     *
+     * @param port port
+     */
+    default void portAdded(Port port) {
+        // do nothing by default
+    }
+
+    /**
+     * Processes the updated port.
+     *
+     * @param port port
+     */
+    default void portUpdated(Port port) {
+        // do nothing by default
+    }
+
+    /**
+     * Processes the removed port.
+     *
+     * @param port port
+     */
+    default void portRemoved(Port port) {
+        // do nothing by default
+    }
+}