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/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);
     }
 }