ONOS-3633 - Implementation of virtual network point to point intent provider.

Change-Id: Ie2c1e5ac278bc0dd6259479c44dd92b9b625e90b
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkCreateCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkCreateCommand.java
index db0e56f..427dddc 100644
--- a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkCreateCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkCreateCommand.java
@@ -20,7 +20,6 @@
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.incubator.net.virtual.NetworkId;
 import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
 import org.onosproject.net.ConnectPoint;
@@ -65,12 +64,10 @@
         VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
         ConnectPoint src = new ConnectPoint(DeviceId.deviceId(srcDeviceId), PortNumber.portNumber(srcPortNum));
         ConnectPoint dst = new ConnectPoint(DeviceId.deviceId(dstDeviceId), PortNumber.portNumber(dstPortNum));
-        //TODO use a real/valid tunnel ID
-        TunnelId tunnelId = TunnelId.valueOf(0);
 
-        service.createVirtualLink(NetworkId.networkId(networkId), src, dst, tunnelId);
+        service.createVirtualLink(NetworkId.networkId(networkId), src, dst);
         if (bidirectional) {
-            service.createVirtualLink(NetworkId.networkId(networkId), dst, src, tunnelId);
+            service.createVirtualLink(NetworkId.networkId(networkId), dst, src);
         }
         print("Virtual link successfully created.");
     }
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkListCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkListCommand.java
index 2f35f66..9f47437 100644
--- a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkListCommand.java
@@ -34,7 +34,7 @@
 public class VirtualLinkListCommand extends AbstractShellCommand {
 
     private static final String FMT_VIRTUAL_LINK =
-            "src=%s, dst=%s";
+            "src=%s, dst=%s, tunnelId=%s";
 
     @Argument(index = 0, name = "networkId", description = "Network ID",
             required = true, multiValued = false)
@@ -65,6 +65,7 @@
      * @param virtualLink virtual link
      */
     private void printVirtualLink(VirtualLink virtualLink) {
-        print(FMT_VIRTUAL_LINK, virtualLink.src().toString(), virtualLink.dst().toString());
+        print(FMT_VIRTUAL_LINK, virtualLink.src().toString(), virtualLink.dst().toString(),
+              virtualLink.tunnelId() == null ? null : virtualLink.tunnelId().toString());
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultLink.java b/core/api/src/main/java/org/onosproject/net/DefaultLink.java
index 739b47e..9aed9c9 100644
--- a/core/api/src/main/java/org/onosproject/net/DefaultLink.java
+++ b/core/api/src/main/java/org/onosproject/net/DefaultLink.java
@@ -148,7 +148,7 @@
     /**
      * Builder for DefaultLink objects.
      */
-    public static final class Builder {
+    public static class Builder {
         private ProviderId providerId;
         private Annotations annotations = EMPTY;
         private ConnectPoint src;
@@ -157,7 +157,7 @@
         private State state = ACTIVE;
         private boolean isExpected = false;
 
-        private Builder() {
+        protected Builder() {
             // Hide constructor
         }
 
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/VirtualLinkCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/VirtualLinkCodec.java
index 54f51e7..9f6b83a 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/VirtualLinkCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/VirtualLinkCodec.java
@@ -1,9 +1,24 @@
+/*
+ * 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.onosproject.codec.impl;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.codec.JsonCodec;
-import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
 import org.onosproject.incubator.net.virtual.NetworkId;
 import org.onosproject.incubator.net.virtual.VirtualLink;
@@ -19,7 +34,6 @@
 
     // JSON field names
     private static final String NETWORK_ID = "networkId";
-    private static final String TUNNEL_ID = "tunnelId";
 
     private static final String NULL_OBJECT_MSG = "VirtualLink cannot be null";
     private static final String MISSING_MEMBER_MSG = " member is required in VirtualLink";
@@ -31,10 +45,6 @@
         JsonCodec<Link> codec = context.codec(Link.class);
         ObjectNode result = codec.encode(vLink, context);
         result.put(NETWORK_ID, vLink.networkId().toString());
-        // TODO check if tunnelId needs to be part of VirtualLink interface.
-        if (vLink instanceof DefaultVirtualLink) {
-            result.put(TUNNEL_ID, ((DefaultVirtualLink) vLink).tunnelId().toString());
-        }
         return result;
     }
 
@@ -46,16 +56,17 @@
         JsonCodec<Link> codec = context.codec(Link.class);
         Link link = codec.decode(json, context);
         NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
-        String tunnelIdStr = json.path(TUNNEL_ID).asText();
-        TunnelId tunnelId = tunnelIdStr != null ? TunnelId.valueOf(tunnelIdStr)
-                : TunnelId.valueOf(0);
-        return new DefaultVirtualLink(nId, link.src(), link.dst(), tunnelId);
+        return DefaultVirtualLink.builder()
+                .networkId(nId)
+                .src(link.src())
+                .dst(link.dst())
+                .build();
     }
 
     /**
      * Extract member from JSON ObjectNode.
      *
-     * @param key key for which value is needed
+     * @param key  key for which value is needed
      * @param json JSON ObjectNode
      * @return member value
      */
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/tunnel/TunnelId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/tunnel/TunnelId.java
index a06ab3a..74a3029 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/tunnel/TunnelId.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/tunnel/TunnelId.java
@@ -23,39 +23,35 @@
  * Representation of a Tunnel Id.
  */
 @Beta
-public final class TunnelId extends Identifier<Long> {
+public final class TunnelId extends Identifier<String> {
     /**
      * Creates an tunnel identifier from the specified tunnel.
      *
-     * @param value long value
+     * @param value string value
      * @return tunnel identifier
      */
-    public static TunnelId valueOf(long value) {
-        return new TunnelId(value);
-    }
-
     public static TunnelId valueOf(String value) {
-         return new TunnelId(Long.parseLong(value));
+        return new TunnelId(value);
     }
 
     /**
      * Constructor for serializer.
      */
     TunnelId() {
-        super(0L);
+        super("0");
     }
 
     /**
-     * Constructs the ID corresponding to a given long value.
+     * Constructs the ID corresponding to a given string value.
      *
      * @param value the underlying value of this ID
      */
-    TunnelId(long value) {
+    TunnelId(String value) {
         super(value);
     }
 
     @Override
     public String toString() {
-        return "0x" + Long.toHexString(identifier);
+        return id();
     }
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualLink.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualLink.java
index 2b86e98..ff42dcd 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualLink.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualLink.java
@@ -25,27 +25,28 @@
 import java.util.Objects;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Default representation of a virtual link.
  */
 public final class DefaultVirtualLink extends DefaultLink implements VirtualLink {
 
-    private static final String VIRTUAL = "virtual";
-    private static final ProviderId PID = new ProviderId(VIRTUAL, VIRTUAL);
+    private static final String VIRTUAL = "virtualLink";
+    public static final ProviderId PID = new ProviderId(VIRTUAL, VIRTUAL);
 
     private final NetworkId networkId;
     private final TunnelId tunnelId;
 
     /**
-     * Constructor for a default virtual link.
+     * Private constructor for a default virtual link.
      *
      * @param networkId network identifier
      * @param src       source connection point
      * @param dst       destination connection point
      * @param tunnelId  tunnel identifier
      */
-    public DefaultVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
+    private DefaultVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
         super(PID, src, dst, Type.VIRTUAL, DefaultAnnotations.builder().build());
         this.networkId = networkId;
         this.tunnelId = tunnelId;
@@ -88,4 +89,84 @@
     public String toString() {
         return toStringHelper(this).add("networkId", networkId).add("tunnelId", tunnelId).toString();
     }
+
+    /**
+     * Creates a new default virtual link builder.
+     *
+     * @return default virtual link builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder for DefaultVirtualLink objects.
+     */
+    public static final class Builder extends DefaultLink.Builder {
+        private NetworkId networkId;
+        private ConnectPoint src;
+        private ConnectPoint dst;
+        private TunnelId tunnelId;
+
+        private Builder() {
+            // Hide constructor
+        }
+
+        /**
+         * Sets the network identifier to be used by the builder.
+         *
+         * @param networkId network identifier
+         * @return self
+         */
+        public Builder networkId(NetworkId networkId) {
+            this.networkId = networkId;
+            return this;
+        }
+
+        /**
+         * Sets the source connect point to be used by the builder.
+         *
+         * @param src source connect point
+         * @return self
+         */
+        public Builder src(ConnectPoint src) {
+            this.src = src;
+            return this;
+        }
+
+        /**
+         * Sets the destination connect point to be used by the builder.
+         *
+         * @param dst new destination connect point
+         * @return self
+         */
+        public Builder dst(ConnectPoint dst) {
+            this.dst = dst;
+            return this;
+        }
+
+        /**
+         * Sets the tunnel identifier to be used by the builder.
+         *
+         * @param tunnelId tunnel identifier
+         * @return self
+         */
+        public Builder tunnelId(TunnelId tunnelId) {
+            this.tunnelId = tunnelId;
+            return this;
+        }
+
+        /**
+         * Builds a default virtual link object from the accumulated parameters.
+         *
+         * @return default virtual link object
+         */
+        public DefaultVirtualLink build() {
+            checkNotNull(src, "Source connect point cannot be null");
+            checkNotNull(dst, "Destination connect point cannot be null");
+            checkNotNull(networkId, "Network Id cannot be null");
+
+            return new DefaultVirtualLink(networkId, src, dst, tunnelId);
+        }
+    }
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualLink.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualLink.java
index ddccb1b..10177a7 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualLink.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualLink.java
@@ -16,6 +16,7 @@
 package org.onosproject.incubator.net.virtual;
 
 import com.google.common.annotations.Beta;
+import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.Link;
 
 /**
@@ -23,4 +24,10 @@
  */
 @Beta
 public interface VirtualLink extends VirtualElement, Link {
+    /**
+     * Returns the tunnel identifier to which this virtual link belongs.
+     *
+     * @return tunnel identifier
+     */
+    TunnelId tunnelId();
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkAdminService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkAdminService.java
index ef22644..c903e61 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkAdminService.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkAdminService.java
@@ -16,7 +16,6 @@
 package org.onosproject.incubator.net.virtual;
 
 import com.google.common.annotations.Beta;
-import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
@@ -96,13 +95,11 @@
      * @param networkId  network identifier
      * @param src        source connection point
      * @param dst        destination connection point
-     * @param realizedBy identifier of the tunnel using which this link is realized
      * @return newly created virtual link
      * @throws org.onlab.util.ItemNotFoundException if no such network found
      */
     VirtualLink createVirtualLink(NetworkId networkId,
-                                  ConnectPoint src, ConnectPoint dst,
-                                  TunnelId realizedBy);
+                                  ConnectPoint src, ConnectPoint dst);
 
     // TODO: Discuss whether we should provide an alternate createVirtualLink
     // which is backed by a Path instead; I'm leaning towards not doing that.
@@ -121,11 +118,11 @@
      * Creates a new virtual port on the specified device.
      *
      * @param networkId  network identifier
-     * @param deviceId   device identifier
-     * @param portNumber port number
-     * @param realizedBy underlying port using which this virtual port is realized
+     * @param deviceId   virtual device identifier
+     * @param portNumber virtual port number
+     * @param realizedBy underlying physical port using which this virtual port is realized
      * @return newly created port
-     * @throws org.onlab.util.ItemNotFoundException if no such network or device found
+     * @throws org.onlab.util.ItemNotFoundException if no such network or device is found
      */
     VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
                                   PortNumber portNumber, Port realizedBy);
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
index 218c77d..35fb0c3 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
@@ -89,11 +89,18 @@
      * @param networkId  network identifier
      * @param src        source end-point of the link
      * @param dst        destination end-point of the link
-     * @param realizedBy underlying tunnel using which this link is realized
+     * @param realizedBy underlying tunnel identifier using which this link is realized
      * @return the virtual link
      */
-    VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
-                        TunnelId realizedBy);
+    VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId realizedBy);
+
+    /**
+     * Updates the tunnelId in the virtual link.
+     *
+     * @param virtualLink  virtual link
+     * @param tunnelId tunnel identifier
+     */
+    void updateLink(VirtualLink virtualLink, TunnelId tunnelId);
 
     /**
      * Removes the specified link from the store.
@@ -101,8 +108,9 @@
      * @param networkId network identifier
      * @param src       source connection point
      * @param dst       destination connection point
+     * @return the virtual link
      */
-    void removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
+    VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
 
     /**
      * Adds a new virtual port to the network.
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/DefaultTunnelTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/DefaultTunnelTest.java
index 2f5a570..e9aa30c 100644
--- a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/DefaultTunnelTest.java
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/DefaultTunnelTest.java
@@ -44,7 +44,7 @@
                 .valueOf(32421));
         DefaultGroupId groupId = new DefaultGroupId(92034);
         TunnelName tunnelName = TunnelName.tunnelName("TunnelName");
-        TunnelId tunnelId = TunnelId.valueOf(41654654);
+        TunnelId tunnelId = TunnelId.valueOf("41654654");
         ProviderId producerName1 = new ProviderId("producer1", "13");
         ProviderId producerName2 = new ProviderId("producer2", "13");
         Tunnel p1 = new DefaultTunnel(producerName1, src, dst, Tunnel.Type.VXLAN,
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelEventTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelEventTest.java
index 307dc50..c38f755 100644
--- a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelEventTest.java
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelEventTest.java
@@ -48,7 +48,7 @@
                 .valueOf(32421));
         DefaultGroupId groupId = new DefaultGroupId(92034);
         TunnelName tunnelName = TunnelName.tunnelName("TunnelName");
-        TunnelId tunnelId = TunnelId.valueOf(41654654);
+        TunnelId tunnelId = TunnelId.valueOf("41654654");
         ProviderId producerName1 = new ProviderId("producer1", "13");
         Tunnel p1 = new DefaultTunnel(producerName1, src, dst, Tunnel.Type.VXLAN,
                                       Tunnel.State.ACTIVE, groupId, tunnelId,
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelIdTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelIdTest.java
index d5159fc..22fac69 100644
--- a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelIdTest.java
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelIdTest.java
@@ -30,9 +30,9 @@
  */
 public class TunnelIdTest {
 
-    final TunnelId tunnelId1 = TunnelId.valueOf(1);
-    final TunnelId sameAstunnelId1 = TunnelId.valueOf(1);
-    final TunnelId tunnelId2 = TunnelId.valueOf(2);
+    final TunnelId tunnelId1 = TunnelId.valueOf("1");
+    final TunnelId sameAstunnelId1 = TunnelId.valueOf("1");
+    final TunnelId tunnelId2 = TunnelId.valueOf("2");
 
     /**
      * Checks that the TunnelId class is immutable.
@@ -58,7 +58,7 @@
      */
     @Test
     public void testConstruction() {
-        final long tunnelIdValue = 7777L;
+        final String tunnelIdValue = "7777";
         final TunnelId tunnelId = TunnelId.valueOf(tunnelIdValue);
         assertThat(tunnelId, is(notNullValue()));
         assertThat(tunnelId.id(), is(tunnelIdValue));
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelSubscriptionTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelSubscriptionTest.java
index 6d69ea745..fc4d04c 100644
--- a/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelSubscriptionTest.java
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/tunnel/TunnelSubscriptionTest.java
@@ -45,7 +45,7 @@
         TunnelEndPoint dst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(32421));
         ApplicationId appId = new DefaultApplicationId(243, "test");
         ApplicationId appId2 = new DefaultApplicationId(2431, "test1");
-        TunnelId tunnelId = TunnelId.valueOf(41654654);
+        TunnelId tunnelId = TunnelId.valueOf("41654654");
         TunnelSubscription p1 = new TunnelSubscription(appId, src, dst, tunnelId, Tunnel.Type.VXLAN,
                              null);
         TunnelSubscription p2 = new TunnelSubscription(appId, src, dst, tunnelId, Tunnel.Type.VXLAN,
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualLinkTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualLinkTest.java
index f522293..71e214a 100644
--- a/incubator/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualLinkTest.java
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualLinkTest.java
@@ -40,6 +40,60 @@
         assertThatClassIsImmutable(DefaultVirtualLink.class);
     }
 
+    /**
+     * Tests the DefaultVirtualLink Builder to ensure that the src cannot be null.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testBuilderNullSrc() {
+        DefaultVirtualDevice device1 =
+                new DefaultVirtualDevice(NetworkId.networkId(0), DeviceId.deviceId(deviceIdValue1));
+        DefaultVirtualDevice device2 =
+                new DefaultVirtualDevice(NetworkId.networkId(0), DeviceId.deviceId(deviceIdValue2));
+        ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+        ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+        DefaultVirtualLink.builder()
+                .src(null)
+                .build();
+    }
+
+    /**
+     * Tests the DefaultVirtualLink Builder to ensure that the dst cannot be null.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testBuilderNullDst() {
+        DefaultVirtualDevice device1 =
+                new DefaultVirtualDevice(NetworkId.networkId(0), DeviceId.deviceId(deviceIdValue1));
+        DefaultVirtualDevice device2 =
+                new DefaultVirtualDevice(NetworkId.networkId(0), DeviceId.deviceId(deviceIdValue2));
+        ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+        ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+        DefaultVirtualLink.builder()
+                .dst(null)
+                .build();
+    }
+
+    /**
+     * Tests the DefaultVirtualLink Builder to ensure that the networkId cannot be null.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testBuilderNullNetworkId() {
+        DefaultVirtualDevice device1 =
+                new DefaultVirtualDevice(NetworkId.networkId(0), DeviceId.deviceId(deviceIdValue1));
+        DefaultVirtualDevice device2 =
+                new DefaultVirtualDevice(NetworkId.networkId(0), DeviceId.deviceId(deviceIdValue2));
+        ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+        ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+        DefaultVirtualLink.builder()
+                .networkId(null)
+                .build();
+    }
+
+    /**
+     * Tests the DefaultVirtualLink equality method.
+     */
     @Test
     public void testEquality() {
         DefaultVirtualDevice device1 =
@@ -49,10 +103,30 @@
         ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
         ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
 
-        DefaultVirtualLink link1 = new DefaultVirtualLink(NetworkId.networkId(0), src, dst, TunnelId.valueOf(0));
-        DefaultVirtualLink link2 = new DefaultVirtualLink(NetworkId.networkId(0), src, dst, TunnelId.valueOf(0));
-        DefaultVirtualLink link3 = new DefaultVirtualLink(NetworkId.networkId(0), src, dst, TunnelId.valueOf(1));
-        DefaultVirtualLink link4 = new DefaultVirtualLink(NetworkId.networkId(1), src, dst, TunnelId.valueOf(0));
+        VirtualLink link1 = DefaultVirtualLink.builder()
+                .networkId(NetworkId.networkId(0))
+                .src(src)
+                .dst(dst)
+                .tunnelId(TunnelId.valueOf("1"))
+                .build();
+        VirtualLink link2 = DefaultVirtualLink.builder()
+                .networkId(NetworkId.networkId(0))
+                .src(src)
+                .dst(dst)
+                .tunnelId(TunnelId.valueOf("1"))
+                .build();
+        VirtualLink link3 = DefaultVirtualLink.builder()
+                .networkId(NetworkId.networkId(0))
+                .src(src)
+                .dst(dst)
+                .tunnelId(TunnelId.valueOf("2"))
+                .build();
+        VirtualLink link4 = DefaultVirtualLink.builder()
+                .networkId(NetworkId.networkId(1))
+                .src(src)
+                .dst(dst)
+                .tunnelId(TunnelId.valueOf("3"))
+                .build();
 
         new EqualsTester().addEqualityGroup(link1, link2).addEqualityGroup(link3)
                 .addEqualityGroup(link4).testEquals();
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/PtToPtIntentVirtualNetworkProvider.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/PtToPtIntentVirtualNetworkProvider.java
new file mode 100644
index 0000000..d879f59
--- /dev/null
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/PtToPtIntentVirtualNetworkProvider.java
@@ -0,0 +1,153 @@
+/*
+ * 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.onosproject.incubator.net.virtual.impl;
+
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
+import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
+import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.EncapsulationType;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.constraint.EncapsulationConstraint;
+import org.onosproject.net.provider.AbstractProvider;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.Thread.sleep;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Point to point intent VirtualNetworkProvider implementation.
+ */
+@Component(immediate = true)
+@Service
+public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider implements VirtualNetworkProvider {
+
+    private final Logger log = getLogger(PtToPtIntentVirtualNetworkProvider.class);
+    private static final String NETWORK_ID_NULL = "Network ID cannot be null";
+    private static final String CONNECT_POINT_NULL = "Connect Point cannot be null";
+    private static final String INTENT_NULL = "Intent cannot be null";
+    protected static final String KEY_FORMAT = "networkId=%s src=%s dst=%s";
+    private static final int MAX_WAIT_COUNT = 30;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected VirtualNetworkProviderRegistry providerRegistry;
+
+    private VirtualNetworkProviderService providerService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected IntentService intentService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    protected static final String PTPT_INTENT_APPID = "org.onosproject.vnet.intent";
+    private ApplicationId appId;
+
+    /**
+     * Default constructor.
+     */
+    public PtToPtIntentVirtualNetworkProvider() {
+        super(DefaultVirtualLink.PID);
+    }
+
+    @Activate
+    public void activate() {
+        providerService = providerRegistry.register(this);
+        appId = coreService.registerApplication(PTPT_INTENT_APPID);
+
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        providerRegistry.unregister(this);
+        providerService = null;
+        log.info("Stopped");
+    }
+
+    @Override
+    public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
+        checkNotNull(NETWORK_ID_NULL, networkId);
+        checkNotNull(CONNECT_POINT_NULL, src);
+        checkNotNull(CONNECT_POINT_NULL, dst);
+        String key = String.format(KEY_FORMAT, networkId.toString(), src.toString(), dst.toString());
+        Key intentKey = Key.of(key, appId);
+
+        List<Constraint> constraints = new ArrayList<>();
+        constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
+
+        // TODO Currently there can only be one tunnel/intent between the src and dst across
+        // all virtual networks. We may want to support multiple intents between the same src/dst pairs.
+        PointToPointIntent intent = PointToPointIntent.builder()
+                .key(intentKey)
+                .appId(appId)
+                .ingressPoint(src)
+                .egressPoint(dst)
+                .constraints(constraints)
+                .build();
+        intentService.submit(intent);
+
+        // construct tunnelId from the key
+        return TunnelId.valueOf(key);
+    }
+
+    @Override
+    public void destroyTunnel(NetworkId networkId, TunnelId tunnelId) {
+        String key = tunnelId.id();
+        Key intentKey = Key.of(key, appId);
+        Intent intent = intentService.getIntent(intentKey);
+        checkNotNull(intent, INTENT_NULL);
+        intentService.withdraw(intent);
+        try {
+            int count = 0;
+            // Loop waiting for the intent to go into a withdrawn or failed state
+            // before attempting to purge it.
+            while (++count <= MAX_WAIT_COUNT) {
+                IntentState state = intentService.getIntentState(intentKey);
+                if ((state == IntentState.FAILED) || (state == IntentState.WITHDRAWN)) {
+                    intentService.purge(intent);
+                    break;
+                }
+                sleep(1000);
+            }
+        } catch (Exception e) {
+            log.error("Exception: " + e);
+        }
+    }
+}
+
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
index fdeed25..b1b68a1 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
@@ -66,6 +66,7 @@
     private static final String NETWORK_NULL = "Network ID cannot be null";
     private static final String DEVICE_NULL = "Device ID cannot be null";
     private static final String LINK_POINT_NULL = "Link end-point cannot be null";
+    private static final String VIRTUAL_LINK_NULL = "Virtual Link cannot be null";
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected VirtualNetworkStore store;
@@ -135,13 +136,41 @@
 
     @Override
     public VirtualLink createVirtualLink(NetworkId networkId,
-                                         ConnectPoint src, ConnectPoint dst,
-                                         TunnelId realizedBy) {
+                                         ConnectPoint src, ConnectPoint dst) {
         checkNotNull(networkId, NETWORK_NULL);
         checkNotNull(src, LINK_POINT_NULL);
         checkNotNull(dst, LINK_POINT_NULL);
-        checkNotNull(realizedBy, "Tunnel ID cannot be null");
-        return store.addLink(networkId, src, dst, realizedBy);
+        VirtualLink virtualLink = store.addLink(networkId, src, dst, null);
+        checkNotNull(virtualLink, VIRTUAL_LINK_NULL);
+
+        if (virtualLink.providerId() != null) {
+            VirtualNetworkProvider provider = getProvider(virtualLink.providerId());
+            if (provider != null) {
+                TunnelId tunnelId = provider.createTunnel(networkId, mapVirtualToPhysicalPort(networkId, src),
+                                                          mapVirtualToPhysicalPort(networkId, dst));
+                store.updateLink(virtualLink, tunnelId);
+            }
+        }
+        return virtualLink;
+    }
+
+    /**
+     * Maps the virtual connect point to a physical connect point.
+     *
+     * @param networkId network identifier
+     * @param virtualCp virtual connect point
+     * @return physical connect point
+     */
+    private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
+                                                  ConnectPoint virtualCp) {
+        Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
+        for (VirtualPort port : ports) {
+            if (port.element().id().equals(virtualCp.elementId()) &&
+                    port.number().equals(virtualCp.port())) {
+                return new ConnectPoint(port.realizedBy().element().id(), port.realizedBy().number());
+            }
+        }
+        return null;
     }
 
     @Override
@@ -149,7 +178,14 @@
         checkNotNull(networkId, NETWORK_NULL);
         checkNotNull(src, LINK_POINT_NULL);
         checkNotNull(dst, LINK_POINT_NULL);
-        store.removeLink(networkId, src, dst);
+        VirtualLink virtualLink = store.removeLink(networkId, src, dst);
+
+        if (virtualLink != null && virtualLink.providerId() != null) {
+            VirtualNetworkProvider provider = getProvider(virtualLink.providerId());
+            if (provider != null) {
+                provider.destroyTunnel(networkId, virtualLink.tunnelId());
+            }
+        }
     }
 
     @Override
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/PtToPtIntentVirtualNetworkProviderTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/PtToPtIntentVirtualNetworkProviderTest.java
new file mode 100644
index 0000000..2f2926b
--- /dev/null
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/PtToPtIntentVirtualNetworkProviderTest.java
@@ -0,0 +1,249 @@
+/*
+ * 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.onosproject.incubator.net.virtual.impl;
+
+import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
+import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
+import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentServiceAdapter;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.provider.AbstractProviderService;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Junit tests for PtToPtIntentVirtualNetworkProvider.
+ */
+public class PtToPtIntentVirtualNetworkProviderTest {
+
+    private PtToPtIntentVirtualNetworkProvider provider;
+    private VirtualNetworkProviderRegistry providerRegistry;
+
+    private final VirtualNetworkRegistryAdapter virtualNetworkRegistry = new VirtualNetworkRegistryAdapter();
+    private IntentService intentService;
+
+    private static final ApplicationId APP_ID =
+            TestApplicationId.create(PtToPtIntentVirtualNetworkProvider.PTPT_INTENT_APPID);
+
+    private IdGenerator idGenerator = new MockIdGenerator();
+
+    @Before
+    public void setUp() {
+        provider = new PtToPtIntentVirtualNetworkProvider();
+        provider.providerRegistry = virtualNetworkRegistry;
+        final CoreService mockCoreService = createMock(CoreService.class);
+        provider.coreService = mockCoreService;
+        expect(mockCoreService.registerApplication(PtToPtIntentVirtualNetworkProvider.PTPT_INTENT_APPID))
+                .andReturn(APP_ID).anyTimes();
+        replay(mockCoreService);
+        Intent.unbindIdGenerator(idGenerator);
+        Intent.bindIdGenerator(idGenerator);
+
+        intentService = new TestIntentService();
+        provider.intentService = intentService;
+        provider.activate();
+    }
+
+    @After
+    public void tearDown() {
+        provider.deactivate();
+        provider.providerRegistry = null;
+        provider.coreService = null;
+        provider.intentService = null;
+        Intent.unbindIdGenerator(idGenerator);
+    }
+
+    @Test
+    public void basics() {
+        assertNotNull("registration expected", provider);
+    }
+
+    /**
+     * Test a null network identifier.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testCreateTunnelNullNetworkId() {
+        provider.createTunnel(null, null, null);
+    }
+
+    /**
+     * Test a null source connect point.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testCreateTunnelNullSrc() {
+        ConnectPoint dst = new ConnectPoint(DeviceId.deviceId("device2"), PortNumber.portNumber(2));
+
+        provider.createTunnel(NetworkId.networkId(0), null, dst);
+    }
+
+    /**
+     * Test a null destination connect point.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testCreateTunnelNullDst() {
+        ConnectPoint src = new ConnectPoint(DeviceId.deviceId("device1"), PortNumber.portNumber(1));
+
+        provider.createTunnel(NetworkId.networkId(0), src, null);
+    }
+
+    /**
+     * Test creating/destroying a valid tunnel.
+     */
+    @Test
+    public void testCreateRemoveTunnel() {
+        NetworkId networkId = NetworkId.networkId(0);
+        ConnectPoint src = new ConnectPoint(DeviceId.deviceId("device1"), PortNumber.portNumber(1));
+        ConnectPoint dst = new ConnectPoint(DeviceId.deviceId("device2"), PortNumber.portNumber(2));
+
+        TunnelId tunnelId = provider.createTunnel(networkId, src, dst);
+        String key = String.format(PtToPtIntentVirtualNetworkProvider.KEY_FORMAT,
+                                   networkId.toString(), src.toString(), dst.toString());
+
+        assertEquals("TunnelId does not match as expected.", key, tunnelId.toString());
+        provider.destroyTunnel(networkId, tunnelId);
+    }
+
+    /**
+     * Virtual network registry implementation for this test class.
+     */
+    private class VirtualNetworkRegistryAdapter implements VirtualNetworkProviderRegistry {
+        private VirtualNetworkProvider provider;
+
+        @Override
+        public VirtualNetworkProviderService register(VirtualNetworkProvider theProvider) {
+            this.provider = theProvider;
+            return new TestVirtualNetworkProviderService(theProvider);
+        }
+
+        @Override
+        public void unregister(VirtualNetworkProvider theProvider) {
+            this.provider = null;
+        }
+
+        @Override
+        public Set<ProviderId> getProviders() {
+            return null;
+        }
+    }
+
+    /**
+     * Virtual network provider service implementation for this test class.
+     */
+    private class TestVirtualNetworkProviderService
+            extends AbstractProviderService<VirtualNetworkProvider>
+            implements VirtualNetworkProviderService {
+
+        protected TestVirtualNetworkProviderService(VirtualNetworkProvider provider) {
+            super(provider);
+        }
+    }
+
+
+    /**
+     * Core service test class.
+     */
+    private class TestCoreService extends CoreServiceAdapter {
+
+        @Override
+        public IdGenerator getIdGenerator(String topic) {
+            return new IdGenerator() {
+                private AtomicLong counter = new AtomicLong(0);
+
+                @Override
+                public long getNewId() {
+                    return counter.getAndIncrement();
+                }
+            };
+        }
+    }
+
+    /**
+     * Represents a fake IntentService class that easily allows to store and
+     * retrieve intents without implementing the IntentService logic.
+     */
+    private class TestIntentService extends IntentServiceAdapter {
+
+        private Set<Intent> intents;
+
+        public TestIntentService() {
+            intents = Sets.newHashSet();
+        }
+
+        @Override
+        public void submit(Intent intent) {
+            intents.add(intent);
+        }
+
+        @Override
+        public void withdraw(Intent intent) {
+        }
+
+        @Override
+        public IntentState getIntentState(Key intentKey) {
+            return IntentState.WITHDRAWN;
+        }
+
+        @Override
+        public void purge(Intent intent) {
+            intents.remove(intent);
+        }
+
+        @Override
+        public long getIntentCount() {
+            return intents.size();
+        }
+
+        @Override
+        public Iterable<Intent> getIntents() {
+            return intents;
+        }
+
+        @Override
+        public Intent getIntent(Key intentKey) {
+            for (Intent intent : intents) {
+                if (intent.key().equals(intentKey)) {
+                    return intent;
+                }
+            }
+            return null;
+        }
+    }
+}
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java
index 214e252..837b501 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java
@@ -27,7 +27,6 @@
 import org.onosproject.core.CoreServiceAdapter;
 import org.onosproject.core.IdGenerator;
 import org.onosproject.event.Event;
-import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
 import org.onosproject.incubator.net.virtual.NetworkId;
 import org.onosproject.incubator.net.virtual.TenantId;
@@ -247,8 +246,8 @@
                 manager.createVirtualDevice(virtualNetwork1.id(), DeviceId.deviceId(deviceIdValue2));
         ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
         ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
-        manager.createVirtualLink(virtualNetwork1.id(), src, dst, TunnelId.valueOf(0));
-        manager.createVirtualLink(virtualNetwork1.id(), dst, src, TunnelId.valueOf(1));
+        manager.createVirtualLink(virtualNetwork1.id(), src, dst);
+        manager.createVirtualLink(virtualNetwork1.id(), dst, src);
 
         Set<VirtualLink> virtualLinks = manager.getVirtualLinks(virtualNetwork1.id());
         assertNotNull("The virtual link set should not be null", virtualLinks);
@@ -263,13 +262,30 @@
         assertTrue("The virtual link set should be empty.", virtualLinks.isEmpty());
 
         // Add/remove the virtual link again.
-        VirtualLink virtualLink = manager.createVirtualLink(virtualNetwork1.id(), src, dst, TunnelId.valueOf(0));
+        VirtualLink virtualLink = manager.createVirtualLink(virtualNetwork1.id(), src, dst);
         manager.removeVirtualLink(virtualLink.networkId(), virtualLink.src(), virtualLink.dst());
         virtualLinks = manager.getVirtualLinks(virtualNetwork1.id());
         assertTrue("The virtual link set should be empty.", virtualLinks.isEmpty());
     }
 
     /**
+     * Tests adding the same virtual link twice.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testAddSameVirtualLink() {
+        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
+        VirtualNetwork virtualNetwork1 = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
+        VirtualDevice srcVirtualDevice =
+                manager.createVirtualDevice(virtualNetwork1.id(), DeviceId.deviceId(deviceIdValue1));
+        VirtualDevice dstVirtualDevice =
+                manager.createVirtualDevice(virtualNetwork1.id(), DeviceId.deviceId(deviceIdValue2));
+        ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
+        ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
+        manager.createVirtualLink(virtualNetwork1.id(), src, dst);
+        manager.createVirtualLink(virtualNetwork1.id(), src, dst);
+    }
+
+    /**
      * Tests add and remove of virtual ports.
      */
     @Test
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java
index 7f5074a..d796068 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java
@@ -180,7 +180,7 @@
             notifyDelegate(event);
             return tunnel.tunnelId();
         } else {
-            TunnelId tunnelId = TunnelId.valueOf(idGenerator.getNewId());
+            TunnelId tunnelId = TunnelId.valueOf(String.valueOf(idGenerator.getNewId()));
             State tunnelState = (state != null) ? state : tunnel.state();
             Tunnel newT = new DefaultTunnel(tunnel.providerId(), tunnel.src(),
                                             tunnel.dst(), tunnel.type(),
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
index ca0c311..f4eedc4 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
@@ -134,9 +134,9 @@
                            .register(DefaultVirtualPort.class)
                            .register(DeviceId.class)
                            .register(Device.class)
-                           .register(TunnelId.class)
                            .register(DefaultDevice.class)
                            .register(DefaultPort.class)
+                           .register(TunnelId.class)
                            .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID).build());
 
     /**
@@ -349,22 +349,51 @@
         if (virtualLinkSet == null) {
             virtualLinkSet = new HashSet<>();
         }
-        VirtualLink virtualLink = new DefaultVirtualLink(networkId, src, dst, realizedBy);
+        // validate that the link does not already exist in this network
+        checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
+
+        VirtualLink virtualLink = DefaultVirtualLink.builder()
+                .networkId(networkId)
+                .src(src)
+                .dst(dst)
+                .tunnelId(realizedBy)
+                .build();
+
         virtualLinkSet.add(virtualLink);
         networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
         return virtualLink;
     }
 
     @Override
-    public void removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
+    public void updateLink(VirtualLink virtualLink, TunnelId tunnelId) {
+        checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
+        Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
+        if (virtualLinkSet == null) {
+            virtualLinkSet = new HashSet<>();
+        }
+        virtualLinkSet.remove(virtualLink);
+
+        VirtualLink newVirtualLink = DefaultVirtualLink.builder()
+                .networkId(virtualLink.networkId())
+                .src(virtualLink.src())
+                .dst(virtualLink.dst())
+                .tunnelId(tunnelId)
+                .build();
+
+        virtualLinkSet.add(newVirtualLink);
+        networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
+    }
+
+    @Override
+    public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
         checkState(networkExists(networkId), "The network has not been added.");
 
+        final VirtualLink virtualLink = getLink(networkId, src, dst);
+        if (virtualLink == null) {
+            return null;
+        }
         Set<VirtualLink> virtualLinkSet = new HashSet<>();
-        networkIdVirtualLinkSetMap.get(networkId).forEach(link -> {
-            if (link.src().equals(src) && link.dst().equals(dst)) {
-                virtualLinkSet.add(link);
-            }
-        });
+        virtualLinkSet.add(virtualLink);
 
         if (virtualLinkSet != null) {
             networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
@@ -375,6 +404,7 @@
                 }
             });
         }
+        return virtualLink;
     }
 
     @Override
@@ -445,6 +475,31 @@
         return ImmutableSet.copyOf(virtualLinkSet);
     }
 
+    /**
+     * Returns the virtual link matching the network identifier, source connect point,
+     * and destination connect point.
+     *
+     * @param networkId network identifier
+     * @param src       source connect point
+     * @param dst       destination connect point
+     * @return virtual link
+     */
+    private VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
+        Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
+        if (virtualLinkSet == null) {
+            return null;
+        }
+
+        VirtualLink virtualLink = null;
+        for (VirtualLink link : virtualLinkSet) {
+            if (link.src().equals(src) && link.dst().equals(dst)) {
+                virtualLink = link;
+                break;
+            }
+        }
+        return virtualLink;
+    }
+
     @Override
     public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
         checkState(networkExists(networkId), "The network has not been added.");
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
index 45ae339..50d54dc 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
@@ -152,7 +152,7 @@
 
     HashMap<String, TunnelId> tunnelMap = new HashMap<String, TunnelId>();
     HashMap<TunnelId, TunnelStatistics> tunnelStatisticsMap = new HashMap<>();
-    private HashMap<Long, TunnelStatsCollector> collectors = Maps.newHashMap();
+    private HashMap<String, TunnelStatsCollector> collectors = Maps.newHashMap();
 
     private InnerTunnelProvider listener = new InnerTunnelProvider();
 
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepReleaseTunnelProviderTest.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepReleaseTunnelProviderTest.java
index bc84599..027f396 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepReleaseTunnelProviderTest.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepReleaseTunnelProviderTest.java
@@ -51,7 +51,7 @@
  */
 public class PcepReleaseTunnelProviderTest {
 
-    public static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
+    private static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
     private PcepTunnelProvider tunnelProvider = new PcepTunnelProvider();
     private final TunnelProviderRegistryAdapter registry = new TunnelProviderRegistryAdapter();
     private final PcepClientControllerAdapter controller = new PcepClientControllerAdapter();
@@ -104,7 +104,7 @@
         path = new DefaultPath(pid, links, 20, EMPTY);
 
         tunnel = new DefaultTunnel(pid, ipTunnelEndPointSrc, ipTunnelEndPointDst, Tunnel.Type.MPLS,
-                                   new DefaultGroupId(0), TunnelId.valueOf(1), TunnelName.tunnelName("T123"),
+                                   new DefaultGroupId(0), TunnelId.valueOf("1"), TunnelName.tunnelName("T123"),
                                    path, EMPTY);
 
         // for releasing tunnel tunnel should exist in db
@@ -154,7 +154,7 @@
         path = new DefaultPath(pid, links, 20, EMPTY);
 
         tunnel = new DefaultTunnel(pid, ipTunnelEndPointSrc, ipTunnelEndPointDst, Tunnel.Type.MPLS,
-                                   new DefaultGroupId(0), TunnelId.valueOf(1), TunnelName.tunnelName("T123"),
+                                   new DefaultGroupId(0), TunnelId.valueOf("1"), TunnelName.tunnelName("T123"),
                                    path, EMPTY);
 
         // for releasing tunnel tunnel should exist in db
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepSetupTunnelProviderTest.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepSetupTunnelProviderTest.java
index 69d9d81..5b41d41 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepSetupTunnelProviderTest.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepSetupTunnelProviderTest.java
@@ -50,7 +50,7 @@
  */
 public class PcepSetupTunnelProviderTest {
 
-    public static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
+    private static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
     private PcepTunnelProvider tunnelProvider = new PcepTunnelProvider();
     private final TunnelProviderRegistryAdapter registry = new TunnelProviderRegistryAdapter();
     private final PcepClientControllerAdapter controller = new PcepClientControllerAdapter();
@@ -99,7 +99,7 @@
         path = new DefaultPath(pid, links, 10, EMPTY);
 
         tunnel = new DefaultTunnel(pid, ipTunnelEndPointSrc, ipTunnelEndPointDst, Tunnel.Type.MPLS,
-                                   new DefaultGroupId(0), TunnelId.valueOf(1), TunnelName.tunnelName("T123"),
+                                   new DefaultGroupId(0), TunnelId.valueOf("1"), TunnelName.tunnelName("T123"),
                                    path, EMPTY);
 
         tunnelProvider.setupTunnel(tunnel, path);
@@ -138,7 +138,7 @@
         path = new DefaultPath(pid, links, 10, EMPTY);
 
         tunnel = new DefaultTunnel(pid, ipTunnelEndPointSrc, ipTunnelEndPointDst, Tunnel.Type.MPLS,
-                                   new DefaultGroupId(0), TunnelId.valueOf(1), TunnelName.tunnelName("T123"),
+                                   new DefaultGroupId(0), TunnelId.valueOf("1"), TunnelName.tunnelName("T123"),
                                    path, EMPTY);
 
         tunnelProvider.setupTunnel(tunnel, path);
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProviderTest.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProviderTest.java
index f339096..d357d46 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProviderTest.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProviderTest.java
@@ -42,7 +42,7 @@
 
 public class PcepTunnelProviderTest {
 
-    public static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
+    private static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
     private PcepTunnelProvider tunnelProvider = new PcepTunnelProvider();
     private final TunnelProviderRegistryAdapter registry = new TunnelProviderRegistryAdapter();
     private final PcepClientControllerAdapter controller = new PcepClientControllerAdapter();
@@ -86,7 +86,7 @@
         path = new DefaultPath(pid, links, 10, EMPTY);
 
         tunnel = new DefaultTunnel(pid, ipTunnelEndPointSrc, ipTunnelEndPointDst, Tunnel.Type.MPLS,
-                                   new DefaultGroupId(0), TunnelId.valueOf(1), TunnelName.tunnelName("T123"),
+                                   new DefaultGroupId(0), TunnelId.valueOf("1"), TunnelName.tunnelName("T123"),
                                    path, EMPTY);
 
         tunnelProvider.setupTunnel(tunnel, path);
diff --git a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepUpdateTunnelProviderTest.java b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepUpdateTunnelProviderTest.java
index e542510..23a2213 100644
--- a/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepUpdateTunnelProviderTest.java
+++ b/providers/pcep/tunnel/src/test/java/org/onosproject/provider/pcep/tunnel/impl/PcepUpdateTunnelProviderTest.java
@@ -51,7 +51,7 @@
  */
 public class PcepUpdateTunnelProviderTest {
 
-    public static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
+    private static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";
     private PcepTunnelProvider tunnelProvider = new PcepTunnelProvider();
     private final TunnelProviderRegistryAdapter registry = new TunnelProviderRegistryAdapter();
     private final PcepClientControllerAdapter controller = new PcepClientControllerAdapter();
@@ -102,7 +102,7 @@
         path = new DefaultPath(pid, links, 20, EMPTY);
 
         tunnel = new DefaultTunnel(pid, ipTunnelEndPointSrc, ipTunnelEndPointDst, Tunnel.Type.MPLS,
-                                   new DefaultGroupId(0), TunnelId.valueOf(1), TunnelName.tunnelName("T123"),
+                                   new DefaultGroupId(0), TunnelId.valueOf("1"), TunnelName.tunnelName("T123"),
                                    path, EMPTY);
 
         // for updating tunnel tunnel should exist in db
@@ -150,7 +150,7 @@
         path = new DefaultPath(pid, links, 20, EMPTY);
 
         tunnel = new DefaultTunnel(pid, ipTunnelEndPointSrc, ipTunnelEndPointDst, Tunnel.Type.MPLS,
-                                   new DefaultGroupId(0), TunnelId.valueOf(1), TunnelName.tunnelName("T123"),
+                                   new DefaultGroupId(0), TunnelId.valueOf("1"), TunnelName.tunnelName("T123"),
                                    path, EMPTY);
 
         // for updating tunnel tunnel should exist in db
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
index d176102..81a699b 100755
--- a/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
@@ -18,8 +18,6 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.incubator.net.tunnel.TunnelId;
-import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
 import org.onosproject.incubator.net.virtual.NetworkId;
 import org.onosproject.incubator.net.virtual.TenantId;
 import org.onosproject.incubator.net.virtual.VirtualDevice;
@@ -100,7 +98,7 @@
     @Path("{tenantId}")
     public Response getVirtualNetworkById(@PathParam("tenantId") String tenantId) {
         final TenantId existingTid = TenantWebResource.getExistingTenantId(vnetAdminService,
-                TenantId.tenantId(tenantId));
+                                                                           TenantId.tenantId(tenantId));
         Set<VirtualNetwork> vnets = vnetService.getVirtualNetworks(existingTid);
         return ok(encodeArray(VirtualNetwork.class, "vnets", vnets)).build();
     }
@@ -158,7 +156,7 @@
     @Path("{networkId}/devices")
     public Response getVirtualDevices(@PathParam("networkId") long networkId) {
         NetworkId nid = NetworkId.networkId(networkId);
-        Set<VirtualDevice> vdevs  = vnetService.getVirtualDevices(nid);
+        Set<VirtualDevice> vdevs = vnetService.getVirtualDevices(nid);
         return ok(encodeArray(VirtualDevice.class, "devices", vdevs)).build();
     }
 
@@ -166,7 +164,7 @@
      * Creates a virtual device from the JSON input stream.
      *
      * @param networkId network identifier
-     * @param stream Virtual device JSON stream
+     * @param stream    Virtual device JSON stream
      * @return status of the request - CREATED if the JSON is correct,
      * BAD_REQUEST if the JSON is invalid
      * @onos.rsModel VirtualDevice
@@ -201,13 +199,13 @@
      * Removes the virtual network device from the virtual network.
      *
      * @param networkId network identifier
-     * @param deviceId device identifier
+     * @param deviceId  device identifier
      * @return 200 OK, 404 not found
      */
     @DELETE
     @Path("{networkId}/devices/{deviceId}")
     public Response removeVirtualDevice(@PathParam("networkId") long networkId,
-            @PathParam("deviceId") String deviceId) {
+                                        @PathParam("deviceId") String deviceId) {
         NetworkId nid = NetworkId.networkId(networkId);
         DeviceId did = DeviceId.deviceId(deviceId);
         vnetAdminService.removeVirtualDevice(nid, did);
@@ -220,25 +218,25 @@
      * Returns all virtual network ports in a virtual device in a virtual network.
      *
      * @param networkId network identifier
-     * @param deviceId virtual device identifier
+     * @param deviceId  virtual device identifier
      * @return 200 OK
      */
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     @Path("{networkId}/devices/{deviceId}/ports")
     public Response getVirtualPorts(@PathParam("networkId") long networkId,
-            @PathParam("deviceId") String deviceId) {
+                                    @PathParam("deviceId") String deviceId) {
         NetworkId nid = NetworkId.networkId(networkId);
-        Iterable<VirtualPort> vports  = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
+        Iterable<VirtualPort> vports = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
         return ok(encodeArray(VirtualPort.class, "ports", vports)).build();
     }
 
     /**
      * Creates a virtual network port in a virtual device in a virtual network.
      *
-     * @param networkId network identifier
+     * @param networkId    network identifier
      * @param virtDeviceId virtual device identifier
-     * @param stream Virtual device JSON stream
+     * @param stream       Virtual device JSON stream
      * @return status of the request - CREATED if the JSON is correct,
      * BAD_REQUEST if the JSON is invalid
      * @onos.rsModel VirtualPort
@@ -248,8 +246,8 @@
     @Produces(MediaType.APPLICATION_JSON)
     @Path("{networkId}/devices/{deviceId}/ports")
     public Response createVirtualPort(@PathParam("networkId") long networkId,
-            @PathParam("deviceId") String virtDeviceId,
-            InputStream stream) {
+                                      @PathParam("deviceId") String virtDeviceId,
+                                      InputStream stream) {
         try {
             ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
 //            final VirtualPort vportReq = codec(VirtualPort.class).decode(jsonTree, this);
@@ -268,11 +266,11 @@
             DeviceId vdevId = DeviceId.deviceId(virtDeviceId);
             DefaultAnnotations annotations = DefaultAnnotations.builder().build();
             Device physDevice = new DefaultDevice(null, DeviceId.deviceId(specifiedPhysDeviceId.asText()),
-                    null, null, null, null, null, null, annotations);
+                                                  null, null, null, null, null, null, annotations);
             Port realizedBy = new DefaultPort(physDevice,
-                    PortNumber.portNumber(specifiedPhysPortNum.asText()), true);
+                                              PortNumber.portNumber(specifiedPhysPortNum.asText()), true);
             VirtualPort vport = vnetAdminService.createVirtualPort(nid, vdevId,
-                    PortNumber.portNumber(specifiedPortNum.asText()), realizedBy);
+                                    PortNumber.portNumber(specifiedPortNum.asText()), realizedBy);
             UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
                     .path("vnets").path(specifiedNetworkId.asText())
                     .path("devices").path(specifiedDeviceId.asText())
@@ -289,18 +287,18 @@
      * Removes the virtual network port from the virtual device in a virtual network.
      *
      * @param networkId network identifier
-     * @param deviceId virtual device identifier
-     * @param portNum virtual port number
+     * @param deviceId  virtual device identifier
+     * @param portNum   virtual port number
      * @return 200 OK, 404 not found
      */
     @DELETE
     @Path("{networkId}/devices/{deviceId}/ports/{portNum}")
     public Response removeVirtualPort(@PathParam("networkId") long networkId,
-            @PathParam("deviceId") String deviceId,
-            @PathParam("portNum") long portNum) {
+                                      @PathParam("deviceId") String deviceId,
+                                      @PathParam("portNum") long portNum) {
         NetworkId nid = NetworkId.networkId(networkId);
         vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId),
-                PortNumber.portNumber(portNum));
+                                           PortNumber.portNumber(portNum));
         return Response.ok().build();
     }
 
@@ -317,15 +315,15 @@
     @Path("{networkId}/links")
     public Response getVirtualLinks(@PathParam("networkId") long networkId) {
         NetworkId nid = NetworkId.networkId(networkId);
-        Set<VirtualLink> vlinks  = vnetService.getVirtualLinks(nid);
+        Set<VirtualLink> vlinks = vnetService.getVirtualLinks(nid);
         return ok(encodeArray(VirtualLink.class, "links", vlinks)).build();
     }
 
-     /**
+    /**
      * Creates a virtual network link from the JSON input stream.
      *
      * @param networkId network identifier
-     * @param stream Virtual device JSON stream
+     * @param stream    Virtual device JSON stream
      * @return status of the request - CREATED if the JSON is correct,
      * BAD_REQUEST if the JSON is invalid
      * @onos.rsModel VirtualLink
@@ -343,12 +341,8 @@
                 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
             }
             final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
-            TunnelId tunnelId = TunnelId.valueOf(0);
-            if (vlinkReq instanceof DefaultVirtualLink) {
-                tunnelId = ((DefaultVirtualLink) vlinkReq).tunnelId();
-            }
             vnetAdminService.createVirtualLink(vlinkReq.networkId(),
-                    vlinkReq.src(), vlinkReq.dst(), tunnelId);
+                                               vlinkReq.src(), vlinkReq.dst());
             UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
                     .path("vnets").path(specifiedNetworkId.asText())
                     .path("links");
@@ -364,7 +358,7 @@
      * Removes the virtual network link from the JSON input stream.
      *
      * @param networkId network identifier
-     * @param stream deviceIds JSON stream
+     * @param stream    deviceIds JSON stream
      * @return 200 OK, 404 not found
      * @onos.rsModel VirtualLink
      */
@@ -372,7 +366,7 @@
     @Path("{networkId}/links")
     @Consumes(MediaType.APPLICATION_JSON)
     public Response removeVirtualLink(@PathParam("networkId") long networkId,
-                                        InputStream stream) {
+                                      InputStream stream) {
         try {
             ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
             JsonNode specifiedNetworkId = jsonTree.get("networkId");
@@ -382,7 +376,7 @@
             }
             final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
             vnetAdminService.removeVirtualLink(vlinkReq.networkId(),
-                    vlinkReq.src(), vlinkReq.dst());
+                                               vlinkReq.src(), vlinkReq.dst());
         } catch (IOException e) {
             throw new IllegalArgumentException(e);
         }
@@ -393,7 +387,7 @@
     /**
      * Get the tenant identifier from the JSON stream.
      *
-     * @param stream TenantId JSON stream
+     * @param stream        TenantId JSON stream
      * @param jsonFieldName field name
      * @return JsonNode
      * @throws IOException if unable to parse the request
diff --git a/web/api/src/main/resources/definitions/VirtualLink.json b/web/api/src/main/resources/definitions/VirtualLink.json
index 2bc7be7..6f79e49 100644
--- a/web/api/src/main/resources/definitions/VirtualLink.json
+++ b/web/api/src/main/resources/definitions/VirtualLink.json
@@ -56,10 +56,6 @@
     "state": {
       "type": "string",
       "example": "ACTIVE"
-    },
-    "tunnelId": {
-      "type": "int64",
-      "example": "Tunnel identifier"
     }
   }
 }
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
index 63c6698..a41f65a 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
@@ -32,7 +32,6 @@
 import org.onlab.rest.BaseResource;
 import org.onosproject.codec.CodecService;
 import org.onosproject.codec.impl.CodecManager;
-import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
 import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
 import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
@@ -104,7 +103,6 @@
     private static final String PORT_NUM = "portNum";
     private static final String PHYS_DEVICE_ID = "physDeviceId";
     private static final String PHYS_PORT_NUM = "physPortNum";
-    private static final String TUNNEL_ID = "tunnelId";
 
     private final TenantId tenantId1 = TenantId.tenantId("TenantId1");
     private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
@@ -137,18 +135,26 @@
     Port port2 = new DefaultPort(dev2, portNumber(2), true);
 
     private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
-                                                              dev22, portNumber(22), port1);
+                                                               dev22, portNumber(22), port1);
     private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
-                                                              dev22, portNumber(23), port2);
+                                                               dev22, portNumber(23), port2);
 
     private final ConnectPoint cp11 = NetTestTools.connectPoint(devId1.toString(), 21);
     private final ConnectPoint cp21 = NetTestTools.connectPoint(devId2.toString(), 22);
     private final ConnectPoint cp12 = NetTestTools.connectPoint(devId1.toString(), 2);
     private final ConnectPoint cp22 = NetTestTools.connectPoint(devId2.toString(), 22);
 
-    private final TunnelId tunnelId = TunnelId.valueOf(31);
-    private final VirtualLink vlink1 = new DefaultVirtualLink(networkId3, cp22, cp11, tunnelId);
-    private final VirtualLink vlink2 = new DefaultVirtualLink(networkId3, cp12, cp21, tunnelId);
+    private final VirtualLink vlink1 = DefaultVirtualLink.builder()
+            .networkId(networkId3)
+            .src(cp22)
+            .dst(cp11)
+            .build();
+
+    private final VirtualLink vlink2 = DefaultVirtualLink.builder()
+            .networkId(networkId3)
+            .src(cp12)
+            .dst(cp21)
+            .build();
 
     /**
      * Sets up the global values for all the tests.
@@ -217,14 +223,14 @@
     /**
      * Factory to allocate a virtual network entity matcher.
      *
-     * @param obj virtual network object we are looking for
+     * @param obj            virtual network object we are looking for
      * @param jsonFieldNames JSON field names to check against
-     * @param getValue function to retrieve value from virtual network object
+     * @param getValue       function to retrieve value from virtual network object
      * @param <T>
      * @return JsonObjectMatcher
      */
     private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames,
-                                                    BiFunction<T, String, String> getValue) {
+                                                           BiFunction<T, String, String> getValue) {
         return new JsonObjectMatcher(obj, jsonFieldNames, getValue);
     }
 
@@ -710,7 +716,7 @@
         final JsonArray vnetJsonArray = result.get("ports").asArray();
         assertThat(vnetJsonArray, notNullValue());
         assertEquals("Virtual ports array is not the correct size.",
-                vportSet.size(), vnetJsonArray.size());
+                     vportSet.size(), vnetJsonArray.size());
 
         vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport)));
 
@@ -759,7 +765,7 @@
         DeviceId deviceId = devId22;
         DefaultAnnotations annotations = DefaultAnnotations.builder().build();
         Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"),
-                null, null, null, null, null, null, annotations);
+                                              null, null, null, null, null, null, annotations);
         Port port1 = new DefaultPort(physDevice, portNumber(1), true);
         expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), port1))
                 .andReturn(vport22);
@@ -817,7 +823,7 @@
         WebTarget wt = target()
                 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
         String reqLocation = "vnets/" + networkId.toString()
-            + "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
+                + "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
         Response response = wt.path(reqLocation)
                 .request(MediaType.APPLICATION_JSON_TYPE)
                 .delete();
@@ -902,15 +908,6 @@
                 reason = ID + " was " + jsonNetworkId;
                 return false;
             }
-            // check TunnelId
-            String jsonTunnelId = jsonLink.get(TUNNEL_ID).asString();
-            if (jsonTunnelId != null && vlink instanceof DefaultVirtualLink) {
-                String tunnelId = ((DefaultVirtualLink) vlink).tunnelId().toString();
-                if (!jsonTunnelId.equals(tunnelId)) {
-                    reason = TUNNEL_ID + " was " + jsonTunnelId;
-                    return false;
-                }
-            }
             return true;
         }
 
@@ -980,7 +977,7 @@
     @Test
     public void testPostVirtualLink() {
         NetworkId networkId = networkId3;
-        expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11, tunnelId))
+        expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11))
                 .andReturn(vlink1);
         replay(mockVnetAdminService);
 
diff --git a/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-link.json b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-link.json
index a7c5d26..8f04673 100644
--- a/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-link.json
+++ b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-link.json
@@ -9,6 +9,5 @@
     "port": "21" 
   },
   "type": "VIRTUAL",
-  "state": "ACTIVE",
-  "tunnelId": "31"
+  "state": "ACTIVE"
 }