pom modifications to appify vtn
renaming package
diff --git a/src/main/java/org/opencord/cordvtn/api/ConnectionHandler.java b/src/main/java/org/opencord/cordvtn/api/ConnectionHandler.java
new file mode 100644
index 0000000..6f032fa
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/ConnectionHandler.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * 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/CordVtnConfig.java b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
new file mode 100644
index 0000000..f4a8cec
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
@@ -0,0 +1,254 @@
+/*
+ * 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;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.Config;
+import org.onosproject.xosclient.api.OpenStackAccess;
+import org.onosproject.xosclient.api.XosAccess;
+import org.slf4j.Logger;
+
+import java.util.Map;
+import java.util.Set;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Configuration object for CordVtn service.
+ */
+public class CordVtnConfig extends Config<ApplicationId> {
+
+    protected final Logger log = getLogger(getClass());
+
+    public static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
+    public static final String PUBLIC_GATEWAYS = "publicGateways";
+    public static final String GATEWAY_IP = "gatewayIp";
+    public static final String GATEWAY_MAC = "gatewayMac";
+    public static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
+    public static final String MANAGEMENT_IP = "managementIpRange";
+    public static final String OVSDB_PORT = "ovsdbPort";
+
+    public static final String CORDVTN_NODES = "nodes";
+    public static final String HOSTNAME = "hostname";
+    public static final String HOST_MANAGEMENT_IP = "hostManagementIp";
+    public static final String DATA_PLANE_IP = "dataPlaneIp";
+    public static final String DATA_PLANE_INTF = "dataPlaneIntf";
+    public static final String BRIDGE_ID = "bridgeId";
+
+    public static final String SSH = "ssh";
+    public static final String SSH_PORT = "sshPort";
+    public static final String SSH_USER = "sshUser";
+    public static final String SSH_KEY_FILE = "sshKeyFile";
+
+    public static final String OPENSTACK = "openstack";
+    public static final String XOS = "xos";
+
+    public static final String ENDPOINT = "endpoint";
+    public static final String TENANT = "tenant";
+    public static final String USER = "user";
+    public static final String PASSWORD = "password";
+
+    /**
+     * Returns the set of nodes read from network config.
+     *
+     * @return set of CordVtnNodeConfig or empty set
+     */
+    public Set<CordVtnNode> cordVtnNodes() {
+
+        Set<CordVtnNode> nodes = Sets.newHashSet();
+
+        JsonNode cordvtnNodes = object.get(CORDVTN_NODES);
+        if (cordvtnNodes == null) {
+            log.debug("No CORD VTN nodes found");
+            return nodes;
+        }
+
+        JsonNode sshNode = object.get(SSH);
+        if (sshNode == null) {
+            log.warn("SSH information not found");
+            return nodes;
+        }
+
+        for (JsonNode cordvtnNode : cordvtnNodes) {
+            try {
+                NetworkAddress hostMgmt = NetworkAddress.valueOf(getConfig(cordvtnNode, HOST_MANAGEMENT_IP));
+                NetworkAddress localMgmt = NetworkAddress.valueOf(getConfig(object, LOCAL_MANAGEMENT_IP));
+                if (hostMgmt.prefix().contains(localMgmt.prefix()) ||
+                        localMgmt.prefix().contains(hostMgmt.prefix())) {
+                    log.error("hostMamt and localMgmt cannot be overlapped, skip this node");
+                    continue;
+                }
+
+                Ip4Address hostMgmtIp = hostMgmt.ip().getIp4Address();
+                SshAccessInfo sshInfo = new SshAccessInfo(
+                        hostMgmtIp,
+                        TpPort.tpPort(Integer.parseInt(getConfig(sshNode, SSH_PORT))),
+                        getConfig(sshNode, SSH_USER), getConfig(sshNode, SSH_KEY_FILE));
+
+                String hostname = getConfig(cordvtnNode, HOSTNAME);
+                CordVtnNode newNode = new CordVtnNode(
+                        hostname, hostMgmt, localMgmt,
+                        NetworkAddress.valueOf(getConfig(cordvtnNode, DATA_PLANE_IP)),
+                        TpPort.tpPort(Integer.parseInt(getConfig(object, OVSDB_PORT))),
+                        sshInfo,
+                        DeviceId.deviceId(getConfig(cordvtnNode, BRIDGE_ID)),
+                        getConfig(cordvtnNode, DATA_PLANE_INTF),
+                        CordVtnNodeState.noState());
+
+                nodes.add(newNode);
+            } catch (IllegalArgumentException | NullPointerException e) {
+                log.error("{}", e);
+            }
+        }
+
+        return nodes;
+    }
+
+    /**
+     * Returns value of a given path. If the path is missing, show log and return
+     * null.
+     *
+     * @param path path
+     * @return value or null
+     */
+    private String getConfig(JsonNode jsonNode, String path) {
+        jsonNode = jsonNode.path(path);
+
+        if (jsonNode.isMissingNode()) {
+            log.error("{} is not configured", path);
+            return null;
+        } else {
+            return jsonNode.asText();
+        }
+    }
+
+    /**
+     * Returns private network gateway MAC address.
+     *
+     * @return mac address, or null
+     */
+    public MacAddress privateGatewayMac() {
+        JsonNode jsonNode = object.get(PRIVATE_GATEWAY_MAC);
+        if (jsonNode == null) {
+            return null;
+        }
+
+        try {
+            return MacAddress.valueOf(jsonNode.asText());
+        } catch (IllegalArgumentException e) {
+            log.error("Wrong MAC address format {}", jsonNode.asText());
+            return null;
+        }
+    }
+
+    /**
+     * Returns public network gateway IP and MAC address pairs.
+     *
+     * @return map of ip and mac address
+     */
+    public Map<IpAddress, MacAddress> publicGateways() {
+        JsonNode jsonNodes = object.get(PUBLIC_GATEWAYS);
+        if (jsonNodes == null) {
+            return Maps.newHashMap();
+        }
+
+        Map<IpAddress, MacAddress> publicGateways = Maps.newHashMap();
+        jsonNodes.forEach(jsonNode -> {
+            try {
+                publicGateways.put(
+                        IpAddress.valueOf(jsonNode.path(GATEWAY_IP).asText()),
+                        MacAddress.valueOf(jsonNode.path(GATEWAY_MAC).asText()));
+            } catch (IllegalArgumentException | NullPointerException e) {
+                log.error("Wrong address format {}", e.toString());
+            }
+        });
+
+        return publicGateways;
+    }
+
+    /**
+     * Returns management IP address range.
+     *
+     * @return management network ip prefix, or null
+     */
+    public IpPrefix managementIpRange() {
+        JsonNode jsonNode = object.get(MANAGEMENT_IP);
+        if (jsonNode == null) {
+            return null;
+        }
+
+        try {
+            return IpPrefix.valueOf(jsonNode.asText());
+        } catch (IllegalArgumentException e) {
+            log.error("{}:{} wrong address format", MANAGEMENT_IP, jsonNode);
+            return null;
+        }
+    }
+
+    /**
+     * Returns XOS access information.
+     *
+     * @return XOS access, or null
+     */
+    public XosAccess xosAccess() {
+        JsonNode jsonNode = object.get(XOS);
+        if (jsonNode == null) {
+            return null;
+        }
+
+        try {
+            return new XosAccess(getConfig(jsonNode, ENDPOINT),
+                                 getConfig(jsonNode, USER),
+                                 getConfig(jsonNode, PASSWORD));
+        } catch (NullPointerException e) {
+            log.error("Failed to get XOS access");
+            return null;
+        }
+    }
+
+    /**
+     * Returns OpenStack API access information.
+     *
+     * @return openstack access
+     */
+    public OpenStackAccess openstackAccess() {
+        JsonNode jsonNode = object.get(OPENSTACK);
+        if (jsonNode == null) {
+            log.error("Failed to get OpenStack configurations");
+            return null;
+        }
+
+        try {
+            return new OpenStackAccess(
+                    jsonNode.path(ENDPOINT).asText(),
+                    jsonNode.path(TENANT).asText(),
+                    jsonNode.path(USER).asText(),
+                    jsonNode.path(PASSWORD).asText());
+        } catch (IllegalArgumentException | NullPointerException e) {
+            log.error("Failed to get OpenStack configurations");
+            return null;
+        }
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/CordVtnNode.java b/src/main/java/org/opencord/cordvtn/api/CordVtnNode.java
new file mode 100644
index 0000000..b251b49
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/CordVtnNode.java
@@ -0,0 +1,220 @@
+/*
+ * 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;
+
+import com.google.common.base.MoreObjects;
+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 NetworkAddress hostMgmtIp;
+    private final NetworkAddress localMgmtIp;
+    private final NetworkAddress dpIp;
+    private final TpPort ovsdbPort;
+    private final SshAccessInfo sshInfo;
+    private final DeviceId bridgeId;
+    private final String dpIntf;
+    private final CordVtnNodeState state;
+
+    public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR =
+            (node1, node2) -> node1.hostname().compareTo(node2.hostname());
+
+    /**
+     * Creates a new node.
+     *
+     * @param hostname hostname
+     * @param hostMgmtIp host management network address
+     * @param localMgmtIp local management network address
+     * @param dpIp data plane network address
+     * @param ovsdbPort port number for OVSDB connection
+     * @param sshInfo SSH access information
+     * @param bridgeId integration bridge identifier
+     * @param dpIntf data plane interface name
+     * @param state cordvtn node state
+     */
+    public CordVtnNode(String hostname, NetworkAddress hostMgmtIp, NetworkAddress localMgmtIp,
+                       NetworkAddress dpIp, TpPort ovsdbPort, SshAccessInfo sshInfo,
+                       DeviceId bridgeId, String dpIntf, CordVtnNodeState state) {
+        this.hostname = checkNotNull(hostname, "hostname cannot be null");
+        this.hostMgmtIp = checkNotNull(hostMgmtIp, "hostMgmtIp cannot be null");
+        this.localMgmtIp = checkNotNull(localMgmtIp, "localMgmtIp cannot be null");
+        this.dpIp = checkNotNull(dpIp, "dpIp cannot be null");
+        this.ovsdbPort = checkNotNull(ovsdbPort, "ovsdbPort cannot be null");
+        this.sshInfo = checkNotNull(sshInfo, "sshInfo cannot be null");
+        this.bridgeId = checkNotNull(bridgeId, "bridgeId cannot be null");
+        this.dpIntf = checkNotNull(dpIntf, "dpIntf cannot be null");
+        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.dpIp,
+                               node.ovsdbPort,
+                               node.sshInfo,
+                               node.bridgeId,
+                               node.dpIntf, state);
+    }
+
+    /**
+     * Returns the hostname.
+     *
+     * @return hostname
+     */
+    public String hostname() {
+        return this.hostname;
+    }
+
+    /**
+     * Returns the host management network address.
+     *
+     * @return network address
+     */
+    public NetworkAddress hostMgmtIp() {
+        return this.hostMgmtIp;
+    }
+
+    /**
+     * Returns the local management network address.
+     *
+     * @return network address
+     */
+    public NetworkAddress localMgmtIp() {
+        return this.localMgmtIp;
+    }
+
+    /**
+     * Returns the data plane network address.
+     *
+     * @return network address
+     */
+    public NetworkAddress dpIp() {
+        return this.dpIp;
+    }
+
+    /**
+     * Returns the port number used for OVSDB connection.
+     *
+     * @return port number
+     */
+    public TpPort ovsdbPort() {
+        return this.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 intBrId() {
+        return this.bridgeId;
+    }
+
+    /**
+     * Returns the identifier of the OVSDB device.
+     *
+     * @return device id
+     */
+    public DeviceId ovsdbId() {
+        return DeviceId.deviceId("ovsdb:" + this.hostMgmtIp.ip().toString());
+    }
+
+    /**
+     * Returns data plane interface name.
+     *
+     * @return data plane interface name
+     */
+    public String dpIntf() {
+        return this.dpIntf;
+    }
+
+    /**
+     * 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(dpIp, that.dpIp) &&
+                    Objects.equals(ovsdbPort, that.ovsdbPort) &&
+                    Objects.equals(sshInfo, that.sshInfo) &&
+                    Objects.equals(bridgeId, that.bridgeId) &&
+                    Objects.equals(dpIntf, that.dpIntf)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(hostname, hostMgmtIp, localMgmtIp, dpIp,
+                            ovsdbPort, sshInfo, bridgeId, dpIntf);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("hostname", hostname)
+                .add("hostMgmtIp", hostMgmtIp)
+                .add("localMgmtIp", localMgmtIp)
+                .add("dpIp", dpIp)
+                .add("port", ovsdbPort)
+                .add("sshInfo", sshInfo)
+                .add("bridgeId", bridgeId)
+                .add("dpIntf", dpIntf)
+                .add("state", state)
+                .toString();
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/CordVtnNodeState.java b/src/main/java/org/opencord/cordvtn/api/CordVtnNodeState.java
new file mode 100644
index 0000000..c95e270
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/CordVtnNodeState.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-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;
+
+/**
+ * Entity that defines possible init state of the cordvtn node.
+ */
+public interface CordVtnNodeState {
+    /**
+     * Returns null for no state.
+     *
+     * @return null
+     */
+    static CordVtnNodeState noState() {
+        return null;
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/CordVtnService.java b/src/main/java/org/opencord/cordvtn/api/CordVtnService.java
new file mode 100644
index 0000000..dd4c2c3
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/CordVtnService.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+import org.onosproject.xosclient.api.VtnServiceId;
+
+/**
+ * Service for provisioning overlay virtual networks on compute nodes.
+ */
+public interface CordVtnService {
+
+    String CORDVTN_APP_ID = "org.onosproject.cordvtn";
+
+    /**
+     * Creates dependencies for a given tenant service.
+     *
+     * @param tServiceId id of the service which has a dependency
+     * @param pServiceId id of the service which provide dependency
+     * @param isBidirectional true to enable bidirectional connectivity between two services
+     */
+    void createServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
+                                 boolean isBidirectional);
+
+    /**
+     * Removes all dependencies from a given tenant service.
+     *
+     * @param tServiceId id of the service which has a dependency
+     * @param pServiceId id of the service which provide dependency
+     */
+    void removeServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId);
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/Instance.java b/src/main/java/org/opencord/cordvtn/api/Instance.java
new file mode 100644
index 0000000..3945a9d
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/Instance.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2016-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;
+
+import com.google.common.base.Strings;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.PortNumber;
+import org.onosproject.xosclient.api.VtnPortId;
+import org.onosproject.xosclient.api.VtnService;
+import org.onosproject.xosclient.api.VtnServiceId;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Provides methods to help to handle network service instance.
+ */
+public final class Instance {
+
+    public static final String SERVICE_ID = "serviceId";
+    public static final String SERVICE_TYPE = "serviceType";
+    public static final String PORT_ID = "vtnPortId";
+    public static final String CREATE_TIME = "createTime";
+    public static final String NESTED_INSTANCE = "nestedInstance";
+    public static final String TRUE = "true";
+
+    private final Host host;
+
+    /**
+     * Default constructor.
+     *
+     * @param instance host object of this instance
+     */
+    private Instance(Host instance) {
+        this.host = instance;
+    }
+
+    /**
+     * Returns host object of this instance.
+     *
+     * @return host
+     */
+    public Host host() {
+        return this.host;
+    }
+
+    /**
+     * Returns new instance.
+     *
+     * @param host host object of this instance
+     * @return instance
+     */
+    public static Instance of(Host host) {
+        checkNotNull(host);
+        checkArgument(!Strings.isNullOrEmpty(host.annotations().value(SERVICE_ID)));
+        checkArgument(!Strings.isNullOrEmpty(host.annotations().value(SERVICE_TYPE)));
+        checkArgument(!Strings.isNullOrEmpty(host.annotations().value(PORT_ID)));
+        checkArgument(!Strings.isNullOrEmpty(host.annotations().value(CREATE_TIME)));
+
+        return new Instance(host);
+    }
+
+    /**
+     * Returns service ID of a given host.
+     *
+     * @return vtn service id
+     */
+    public VtnServiceId serviceId() {
+        String serviceId = host.annotations().value(SERVICE_ID);
+        return VtnServiceId.of(serviceId);
+    }
+
+    /**
+     * Returns service type of a given host.
+     *
+     * @return vtn service type
+     */
+    public VtnService.ServiceType serviceType() {
+        String serviceType = host.annotations().value(SERVICE_TYPE);
+        return VtnService.ServiceType.valueOf(serviceType);
+    }
+
+    /**
+     * Returns port ID of a given host.
+     *
+     * @return vtn port id
+     */
+    public VtnPortId portId() {
+        String portId = host.annotations().value(PORT_ID);
+        return VtnPortId.of(portId);
+    }
+
+    /**
+     * Returns if the instance is nested container or not.
+     *
+     * @return true if it's nested container; false otherwise
+     */
+    public boolean isNestedInstance() {
+        return host.annotations().value(NESTED_INSTANCE) != null;
+    }
+
+    /**
+     * Returns MAC address of this instance.
+     *
+     * @return mac address
+     */
+    public MacAddress mac() {
+        return host.mac();
+    }
+
+    /**
+     * Returns IP address of this instance.
+     *
+     * @return ip address
+     */
+    public Ip4Address ipAddress() {
+        // assume all instance has only one IP address, and only IP4 is supported now
+        return host.ipAddresses().stream().findFirst().get().getIp4Address();
+    }
+
+    /**
+     * Returns device ID of this host.
+     *
+     * @return device id
+     */
+    public DeviceId deviceId() {
+        return host.location().deviceId();
+    }
+
+    /**
+     * Returns the port number where this host is.
+     *
+     * @return port number
+     */
+    public PortNumber portNumber() {
+        return host.location().port();
+    }
+
+    /**
+     * Returns annotation value with a given key.
+     *
+     * @param annotationKey annotation key
+     * @return annotation value
+     */
+    public String getAnnotation(String annotationKey) {
+        return host.annotations().value(annotationKey);
+    }
+
+    @Override
+    public String toString() {
+        return host.toString();
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/InstanceHandler.java b/src/main/java/org/opencord/cordvtn/api/InstanceHandler.java
new file mode 100644
index 0000000..ea44857
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/InstanceHandler.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-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;
+
+/**
+ * Handles service instance detection and removal.
+ */
+public interface InstanceHandler {
+
+    /**
+     * Handles newly detected instance.
+     *
+     * @param instance instance
+     */
+    void instanceDetected(Instance instance);
+
+    /**
+     * Handles removed instance.
+     *
+     * @param instance instance
+     */
+    void instanceRemoved(Instance instance);
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/NetworkAddress.java b/src/main/java/org/opencord/cordvtn/api/NetworkAddress.java
new file mode 100644
index 0000000..551d084
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/NetworkAddress.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016-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;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Representation of a network address, which consists of IP address and prefix.
+ */
+public final class NetworkAddress {
+    private final IpAddress ip;
+    private final IpPrefix prefix;
+
+    /**
+     * Constructor for a given IP address and prefix.
+     *
+     * @param ip ip address
+     * @param prefix ip prefix
+     */
+    public NetworkAddress(IpAddress ip, IpPrefix prefix) {
+        this.ip = ip;
+        this.prefix = prefix;
+    }
+
+    /**
+     * Converts a CIDR notation string into a network address.
+     *
+     * @param cidr cidr
+     * @return network address
+     * @throws IllegalArgumentException if the cidr is not valid
+     */
+    public static NetworkAddress valueOf(String cidr) {
+        checkArgument(cidr.contains("/"));
+
+        IpAddress ipAddress = IpAddress.valueOf(cidr.split("/")[0]);
+        IpPrefix ipPrefix = IpPrefix.valueOf(cidr);
+
+        return new NetworkAddress(ipAddress, ipPrefix);
+    }
+
+    /**
+     * Returns the IP address value of the network address.
+     *
+     * @return ip address
+     */
+    public IpAddress ip() {
+        return this.ip;
+    }
+
+    /**
+     * Returns the IP prefix value of the network address.
+     *
+     * @return ip prefix
+     */
+    public IpPrefix prefix() {
+        return this.prefix;
+    }
+
+    /**
+     * Converts a network address to a CIDR notation.
+     *
+     * @return cidr notation string
+     */
+    public String cidr() {
+        return ip.toString() + "/" + prefix.prefixLength();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof NetworkAddress) {
+            NetworkAddress that = (NetworkAddress) obj;
+            if (Objects.equals(ip, that.ip) && Objects.equals(prefix, that.prefix)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ip, prefix);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("IpAddress", ip)
+                .add("IpPrefix", prefix)
+                .toString();
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/SshAccessInfo.java b/src/main/java/org/opencord/cordvtn/api/SshAccessInfo.java
new file mode 100644
index 0000000..3a85978
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/SshAccessInfo.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2016-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;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.TpPort;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of SSH access information.
+ */
+public final class SshAccessInfo {
+
+    private final Ip4Address remoteIp;
+    private final TpPort port;
+    private final String user;
+    private final String privateKey;
+
+    /**
+     * Creates a new SSH access information.
+     *
+     * @param remoteIp ssh remote ip address
+     * @param port ssh port number
+     * @param user user name
+     * @param privateKey path of ssh private key
+     */
+    public SshAccessInfo(Ip4Address remoteIp, TpPort port, String user, String privateKey) {
+        this.remoteIp = checkNotNull(remoteIp);
+        this.port = checkNotNull(port);
+        this.user = checkNotNull(user);
+        this.privateKey = checkNotNull(privateKey);
+    }
+
+    /**
+     * Returns the remote IP address.
+     *
+     * @return ip address
+     */
+    public Ip4Address remoteIp() {
+        return this.remoteIp;
+    }
+
+    /**
+     * Returns the port number.
+     *
+     * @return ssh port
+     */
+    public TpPort port() {
+        return this.port;
+    }
+
+    /**
+     * Returns the user name.
+     *
+     * @return user name
+     */
+    public String user() {
+        return this.user;
+    }
+
+    /**
+     * Returns the private key path.
+     *
+     * @return privateKey
+     */
+    public String privateKey() {
+        return privateKey;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof SshAccessInfo) {
+            SshAccessInfo that = (SshAccessInfo) obj;
+            if (Objects.equals(remoteIp, that.remoteIp) &&
+                    Objects.equals(port, that.port) &&
+                    Objects.equals(user, that.user) &&
+                    Objects.equals(privateKey, that.privateKey)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(remoteIp, port, user, privateKey);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("remoteIp", remoteIp)
+                .add("port", port)
+                .add("user", user)
+                .add("privateKey", privateKey)
+                .toString();
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/package-info.java b/src/main/java/org/opencord/cordvtn/api/package-info.java
new file mode 100644
index 0000000..3aa14b6
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-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.
+ */
+
+/**
+ * API for CORD VTN application.
+ */
+package org.opencord.cordvtn.api;
\ No newline at end of file