ONOS-4076 - Virtual Network CLI commands and bug fixes in
DistributedVirtualNetworkStore.

Change-Id: I7bf67527bccb598385f15ad70091e3f8458d35d3
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/TenantAddCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/TenantAddCommand.java
new file mode 100644
index 0000000..b7f8a2e
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/TenantAddCommand.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+
+/**
+ * Creates a new virtual network tenant.
+ */
+@Command(scope = "onos", name = "vnet-add-tenant",
+        description = "Creates a new virtual network tenant.")
+
+public class TenantAddCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "id", description = "Tenant ID",
+            required = true, multiValued = false)
+    String id = null;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        service.registerTenantId(TenantId.tenantId(id));
+        print("Tenant successfully added.");
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/TenantListCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/TenantListCommand.java
new file mode 100644
index 0000000..13fb052
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/TenantListCommand.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.utils.Comparators;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all tenants.
+ */
+@Command(scope = "onos", name = "vnet-tenants",
+        description = "Lists all virtual network tenants.")
+public class TenantListCommand extends AbstractShellCommand {
+
+    private static final String FMT_TENANT = "tenantId=%s";
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        List<TenantId> tenants = new ArrayList<>();
+        tenants.addAll(service.getTenantIds());
+        Collections.sort(tenants, Comparators.TENANT_ID_COMPARATOR);
+
+        tenants.forEach(this::printTenant);
+    }
+
+    private void printTenant(TenantId tenantId) {
+        print(FMT_TENANT, tenantId.id());
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/TenantRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/TenantRemoveCommand.java
new file mode 100644
index 0000000..e584695
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/TenantRemoveCommand.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+
+/**
+ * Creates a new virtual network tenant.
+ */
+@Command(scope = "onos", name = "vnet-remove-tenant",
+        description = "Removes a virtual network tenant.")
+
+public class TenantRemoveCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "id", description = "Tenant ID",
+            required = true, multiValued = false)
+    String id = null;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        service.unregisterTenantId(TenantId.tenantId(id));
+        print("Tenant successfully removed.");
+    }
+}
\ No newline at end of file
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceCreateCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceCreateCommand.java
new file mode 100644
index 0000000..34047f1
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceCreateCommand.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Creates a new virtual device.
+ */
+@Command(scope = "onos", name = "vnet-create-device",
+        description = "Creates a new virtual device in a network.")
+public class VirtualDeviceCreateCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Argument(index = 1, name = "deviceId", description = "Device ID",
+            required = true, multiValued = false)
+    String deviceId = null;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        service.createVirtualDevice(NetworkId.networkId(networkId), DeviceId.deviceId(deviceId));
+        print("Virtual device successfully created.");
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceListCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceListCommand.java
new file mode 100644
index 0000000..a1fa7a6
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceListCommand.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.utils.Comparators;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all virtual devices for the network ID.
+ */
+@Command(scope = "onos", name = "vnet-devices",
+        description = "Lists all virtual devices in a virtual network.")
+public class VirtualDeviceListCommand extends AbstractShellCommand {
+
+    private static final String FMT_VIRTUAL_DEVICE =
+            "deviceId=%s";
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Override
+    protected void execute() {
+
+        getSortedVirtualDevices().forEach(this::printVirtualDevice);
+    }
+
+    /**
+     * Returns the list of virtual devices sorted using the device identifier.
+     *
+     * @return sorted virtual device list
+     */
+    private List<VirtualDevice> getSortedVirtualDevices() {
+        VirtualNetworkService service = get(VirtualNetworkService.class);
+
+        List<VirtualDevice> virtualDevices = new ArrayList<>();
+        virtualDevices.addAll(service.getVirtualDevices(NetworkId.networkId(networkId)));
+        Collections.sort(virtualDevices, Comparators.VIRTUAL_DEVICE_COMPARATOR);
+        return virtualDevices;
+    }
+
+    /**
+     * Prints out each virtual device.
+     *
+     * @param virtualDevice virtual device
+     */
+    private void printVirtualDevice(VirtualDevice virtualDevice) {
+        print(FMT_VIRTUAL_DEVICE, virtualDevice.id());
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceRemoveCommand.java
new file mode 100644
index 0000000..446c0c3
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualDeviceRemoveCommand.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Removes a virtual device.
+ */
+@Command(scope = "onos", name = "vnet-remove-device",
+        description = "Removes a virtual device.")
+public class VirtualDeviceRemoveCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Argument(index = 1, name = "deviceId", description = "Device ID",
+            required = true, multiValued = false)
+    String deviceId = null;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        service.removeVirtualDevice(NetworkId.networkId(networkId), DeviceId.deviceId(deviceId));
+        print("Virtual device successfully removed.");
+    }
+}
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
new file mode 100644
index 0000000..7b4d0ea
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkCreateCommand.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+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;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+/**
+ * Creates a new virtual link.
+ */
+@Command(scope = "onos", name = "vnet-create-link",
+        description = "Creates a new virtual link in a network.")
+public class VirtualLinkCreateCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Argument(index = 1, name = "srcDeviceId", description = "Source device ID",
+            required = true, multiValued = false)
+    String srcDeviceId = null;
+
+    @Argument(index = 2, name = "srcPortNum", description = "Source port number",
+            required = true, multiValued = false)
+    Integer srcPortNum = null;
+
+    @Argument(index = 3, name = "dstDeviceId", description = "Destination device ID",
+            required = true, multiValued = false)
+    String dstDeviceId = null;
+
+    @Argument(index = 4, name = "dstPortNum", description = "Destination port number",
+            required = true, multiValued = false)
+    Integer dstPortNum = null;
+
+    @Option(name = "-b", aliases = "--bidirectional",
+            description = "If this argument is passed in then the virtual link created will be bidirectional, " +
+                    "otherwise the link will be unidirectional.",
+            required = false, multiValued = false)
+    boolean bidirectional = false;
+
+    @Override
+    protected void execute() {
+        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);
+        if (bidirectional) {
+            service.createVirtualLink(NetworkId.networkId(networkId), dst, src, tunnelId);
+        }
+        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
new file mode 100644
index 0000000..b2e2060
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkListCommand.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualLink;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Lists all virtual links for the network ID.
+ */
+@Command(scope = "onos", name = "vnet-links",
+        description = "Lists all virtual links in a virtual network.")
+public class VirtualLinkListCommand extends AbstractShellCommand {
+
+    private static final String FMT_VIRTUAL_LINK =
+            "src=%s, dst=%s";
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Override
+    protected void execute() {
+
+        getSortedVirtualLinks().forEach(this::printVirtualLink);
+    }
+
+    /**
+     * Returns the list of virtual links sorted using the device identifier.
+     *
+     * @return virtual link list
+     */
+    private List<VirtualLink> getSortedVirtualLinks() {
+        VirtualNetworkService service = get(VirtualNetworkService.class);
+
+        List<VirtualLink> virtualLinks = new ArrayList<>();
+        virtualLinks.addAll(service.getVirtualLinks(NetworkId.networkId(networkId)));
+        return virtualLinks;
+    }
+
+    /**
+     * Prints out each virtual link.
+     *
+     * @param virtualLink virtual link
+     */
+    private void printVirtualLink(VirtualLink virtualLink) {
+        print(FMT_VIRTUAL_LINK, virtualLink.src().toString(), virtualLink.dst().toString());
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkRemoveCommand.java
new file mode 100644
index 0000000..605925f
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualLinkRemoveCommand.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+/**
+ * Removes a virtual link.
+ */
+@Command(scope = "onos", name = "vnet-remove-link",
+        description = "Removes a virtual link.")
+public class VirtualLinkRemoveCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Argument(index = 1, name = "srcDeviceId", description = "Source device ID",
+            required = true, multiValued = false)
+    String srcDeviceId = null;
+
+    @Argument(index = 2, name = "srcPortNum", description = "Source port number",
+            required = true, multiValued = false)
+    Integer srcPortNum = null;
+
+    @Argument(index = 3, name = "dstDeviceId", description = "Destination device ID",
+            required = true, multiValued = false)
+    String dstDeviceId = null;
+
+    @Argument(index = 4, name = "dstPortNum", description = "Destination port number",
+            required = true, multiValued = false)
+    Integer dstPortNum = null;
+
+    @Option(name = "-b", aliases = "--bidirectional",
+            description = "If this argument is passed in then then bidirectional virtual link will be removed, " +
+                    "otherwise the unidirectional link will be removed.",
+            required = false, multiValued = false)
+    boolean bidirectional = false;
+
+    @Override
+    protected void execute() {
+        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));
+
+        service.removeVirtualLink(NetworkId.networkId(networkId), src, dst);
+        if (bidirectional) {
+            service.removeVirtualLink(NetworkId.networkId(networkId), dst, src);
+        }
+        print("Virtual link successfully removed.");
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkCreateCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkCreateCommand.java
new file mode 100644
index 0000000..47038d4
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkCreateCommand.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+
+/**
+ * Creates a new virtual network.
+ */
+@Command(scope = "onos", name = "vnet-create",
+        description = "Creates a new virtual network.")
+public class VirtualNetworkCreateCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "id", description = "Tenant ID",
+            required = true, multiValued = false)
+    String id = null;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        service.createVirtualNetwork(TenantId.tenantId(id));
+        print("Virtual network successfully created.");
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkListCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkListCommand.java
new file mode 100644
index 0000000..35603d0
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkListCommand.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.utils.Comparators;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Lists all virtual networks for the tenant ID.
+ */
+@Command(scope = "onos", name = "vnets",
+        description = "Lists all virtual networks.")
+public class VirtualNetworkListCommand extends AbstractShellCommand {
+
+    private static final String FMT_VIRTUAL_NETWORK =
+            "tenantId=%s, networkId=%s";
+
+    @Override
+    protected void execute() {
+
+        getSortedVirtualNetworks().forEach(this::printVirtualNetwork);
+    }
+
+    /**
+     * Returns the list of virtual networks sorted using the tenant identifier.
+     *
+     * @return sorted virtual network list
+     */
+    private List<VirtualNetwork> getSortedVirtualNetworks() {
+        VirtualNetworkService service = get(VirtualNetworkService.class);
+        VirtualNetworkAdminService adminService = get(VirtualNetworkAdminService.class);
+
+        List<VirtualNetwork> virtualNetworks = new ArrayList<>();
+
+        Set<TenantId> tenantSet = adminService.getTenantIds();
+        tenantSet.forEach(tenantId -> virtualNetworks.addAll(service.getVirtualNetworks(tenantId)));
+
+        Collections.sort(virtualNetworks, Comparators.VIRTUAL_NETWORK_COMPARATOR);
+        return virtualNetworks;
+    }
+
+    /**
+     * Prints out each virtual network.
+     *
+     * @param virtualNetwork virtual network
+     */
+    private void printVirtualNetwork(VirtualNetwork virtualNetwork) {
+        print(FMT_VIRTUAL_NETWORK, virtualNetwork.tenantId(), virtualNetwork.id());
+    }
+}
+
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkRemoveCommand.java
new file mode 100644
index 0000000..4cccac5
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkRemoveCommand.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+
+/**
+ * Removes a virtual network.
+ */
+@Command(scope = "onos", name = "vnet-remove",
+        description = "Removes a virtual network.")
+public class VirtualNetworkRemoveCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "id", description = "Network ID",
+            required = true, multiValued = false)
+    Long id;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        service.removeVirtualNetwork(NetworkId.networkId(id));
+        print("Virtual network successfully removed.");
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortCreateCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortCreateCommand.java
new file mode 100644
index 0000000..b09c30b
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortCreateCommand.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultPort;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Creates a new virtual port.
+ */
+@Command(scope = "onos", name = "vnet-create-port",
+        description = "Creates a new virtual port in a network.")
+public class VirtualPortCreateCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Argument(index = 1, name = "deviceId", description = "Virtual Device ID",
+            required = true, multiValued = false)
+    String deviceId = null;
+
+    @Argument(index = 2, name = "portNum", description = "Virtual device port number",
+            required = true, multiValued = false)
+    Integer portNum = null;
+
+    @Argument(index = 3, name = "physDeviceId", description = "Physical Device ID",
+            required = true, multiValued = false)
+    String physDeviceId = null;
+
+    @Argument(index = 4, name = "physPortNum", description = "Physical device port number",
+            required = true, multiValued = false)
+    Integer physPortNum = null;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        DeviceService deviceService = get(DeviceService.class);
+        VirtualDevice virtualDevice = getVirtualDevice(DeviceId.deviceId(deviceId));
+        checkNotNull(virtualDevice, "The virtual device does not exist.");
+
+        DefaultAnnotations annotations = DefaultAnnotations.builder().build();
+        Device physDevice = new DefaultDevice(null, DeviceId.deviceId(physDeviceId),
+                                              null, null, null, null, null, null, annotations);
+        Port realizedBy = new DefaultPort(physDevice, PortNumber.portNumber(physPortNum), true);
+        service.createVirtualPort(NetworkId.networkId(networkId), DeviceId.deviceId(deviceId),
+                                  PortNumber.portNumber(portNum), realizedBy);
+        print("Virtual port successfully created.");
+    }
+
+    /**
+     * Returns the virtual device matching the device identifier.
+     *
+     * @param aDeviceId device identifier
+     * @return matching virtual device, or null.
+     */
+    private VirtualDevice getVirtualDevice(DeviceId aDeviceId) {
+        VirtualNetworkService service = get(VirtualNetworkService.class);
+
+        Set<VirtualDevice> virtualDevices = service.getVirtualDevices(NetworkId.networkId(networkId));
+
+        for (VirtualDevice virtualDevice : virtualDevices) {
+            if (virtualDevice.id().equals(aDeviceId)) {
+                return virtualDevice;
+            }
+        }
+        return null;
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortListCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortListCommand.java
new file mode 100644
index 0000000..265ff4f
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortListCommand.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.incubator.net.virtual.VirtualPort;
+import org.onosproject.net.DeviceId;
+import org.onosproject.utils.Comparators;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all virtual ports for the network ID.
+ */
+@Command(scope = "onos", name = "vnet-ports",
+        description = "Lists all virtual ports in a virtual network.")
+public class VirtualPortListCommand extends AbstractShellCommand {
+
+    private static final String FMT_VIRTUAL_PORT =
+            "virtual portNumber=%s, physical deviceId=%s, portNumber=%s";
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Argument(index = 1, name = "deviceId", description = "Virtual Device ID",
+            required = true, multiValued = false)
+    String deviceId = null;
+
+    @Override
+    protected void execute() {
+
+        getSortedVirtualPorts().forEach(this::printVirtualPort);
+    }
+
+    /**
+     * Returns the list of virtual ports sorted using the network identifier.
+     *
+     * @return sorted virtual port list
+     */
+    private List<VirtualPort> getSortedVirtualPorts() {
+        VirtualNetworkService service = get(VirtualNetworkService.class);
+
+        List<VirtualPort> virtualPorts = new ArrayList<>();
+        virtualPorts.addAll(service.getVirtualPorts(NetworkId.networkId(networkId), DeviceId.deviceId(deviceId)));
+        Collections.sort(virtualPorts, Comparators.VIRTUAL_PORT_COMPARATOR);
+        return virtualPorts;
+    }
+
+    /**
+     * Prints out each virtual port.
+     *
+     * @param virtualPort virtual port
+     */
+    private void printVirtualPort(VirtualPort virtualPort) {
+        print(FMT_VIRTUAL_PORT, virtualPort.number(),
+              virtualPort.realizedBy().element().id(), virtualPort.realizedBy().number());
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortRemoveCommand.java
new file mode 100644
index 0000000..58ae2fa
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualPortRemoveCommand.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 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.cli.net.vnet;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+/**
+ * Removes a virtual port.
+ */
+@Command(scope = "onos", name = "vnet-remove-port",
+        description = "Removes a virtual port.")
+public class VirtualPortRemoveCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "networkId", description = "Network ID",
+            required = true, multiValued = false)
+    Long networkId = null;
+
+    @Argument(index = 1, name = "deviceId", description = "Device ID",
+            required = true, multiValued = false)
+    String deviceId = null;
+
+    @Argument(index = 2, name = "portNum", description = "Device port number",
+            required = true, multiValued = false)
+    Integer portNum = null;
+
+    @Override
+    protected void execute() {
+        VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
+        service.removeVirtualPort(NetworkId.networkId(networkId), DeviceId.deviceId(deviceId),
+                                  PortNumber.portNumber(portNum));
+        print("Virtual port successfully removed.");
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/package-info.java b/cli/src/main/java/org/onosproject/cli/net/vnet/package-info.java
new file mode 100644
index 0000000..1f2861c
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 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.
+ */
+
+/**
+ * CLI commands for querying and administering virtual networks.
+ */
+package org.onosproject.cli.net.vnet;
\ No newline at end of file
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index a7f533e..9aa0b89 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -1,5 +1,5 @@
 <!--
-  ~ Copyright 2014 Open Networking Laboratory
+  ~ Copyright 2016 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.
@@ -613,6 +613,53 @@
                 <ref component-id="deviceIdCompleter"/>
             </completers>
         </command>
+
+        <!--virtual network commands -->
+        <command>
+            <action class="org.onosproject.cli.net.vnet.TenantListCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.TenantAddCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.TenantRemoveCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualNetworkListCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualNetworkCreateCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualNetworkRemoveCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualDeviceListCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualDeviceCreateCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualDeviceRemoveCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualLinkListCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualLinkCreateCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualLinkRemoveCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualPortListCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualPortCreateCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.vnet.VirtualPortRemoveCommand"/>
+        </command>
     </command-bundle>
 
     <bean id="reviewAppNameCompleter" class="org.onosproject.cli.security.ReviewApplicationNameCompleter"/>
diff --git a/core/common/src/main/java/org/onosproject/utils/Comparators.java b/core/common/src/main/java/org/onosproject/utils/Comparators.java
index f50ef1a..a2a1114 100644
--- a/core/common/src/main/java/org/onosproject/utils/Comparators.java
+++ b/core/common/src/main/java/org/onosproject/utils/Comparators.java
@@ -19,6 +19,10 @@
 import org.onosproject.core.Application;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+import org.onosproject.incubator.net.virtual.VirtualPort;
 import org.onosproject.net.key.DeviceKey;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Element;
@@ -149,4 +153,32 @@
             return region1.id().toString().compareTo(region2.id().toString());
         }
     };
+
+    public static final Comparator<TenantId> TENANT_ID_COMPARATOR = new Comparator<TenantId>() {
+        @Override
+        public int compare(TenantId tenant1, TenantId tenant2) {
+            return tenant1.id().toString().compareTo(tenant2.id().toString());
+        }
+    };
+
+    public static final Comparator<VirtualNetwork> VIRTUAL_NETWORK_COMPARATOR = new Comparator<VirtualNetwork>() {
+        @Override
+        public int compare(VirtualNetwork virtualNetwork1, VirtualNetwork virtualNetwork2) {
+            return virtualNetwork1.tenantId().toString().compareTo(virtualNetwork2.tenantId().toString());
+        }
+    };
+
+    public static final Comparator<VirtualDevice> VIRTUAL_DEVICE_COMPARATOR = new Comparator<VirtualDevice>() {
+        @Override
+        public int compare(VirtualDevice virtualDevice1, VirtualDevice virtualDevice2) {
+            return virtualDevice1.id().toString().compareTo(virtualDevice2.id().toString());
+        }
+    };
+
+    public static final Comparator<VirtualPort> VIRTUAL_PORT_COMPARATOR = new Comparator<VirtualPort>() {
+        @Override
+        public int compare(VirtualPort virtualPort1, VirtualPort virtualPort2) {
+            return virtualPort1.number().toString().compareTo(virtualPort2.number().toString());
+        }
+    };
 }
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 8976a7e..f2ce5c4 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
@@ -146,17 +146,30 @@
         assertNotNull("The virtual network set should not be null", virtualNetworks);
         assertEquals("The virtual network set size did not match.", 2, virtualNetworks.size());
 
+        int remaining = virtualNetworks.size();
         for (VirtualNetwork virtualNetwork : virtualNetworks) {
             manager.removeVirtualNetwork(virtualNetwork.id());
+            assertEquals("The expected virtual network size does not match",
+                         --remaining, manager.getVirtualNetworks(TenantId.tenantId(tenantIdValue1)).size());
             // attempt to remove the same virtual network again.
             manager.removeVirtualNetwork(virtualNetwork.id());
+            assertEquals("The expected virtual network size does not match",
+                         remaining, manager.getVirtualNetworks(TenantId.tenantId(tenantIdValue1)).size());
         }
         virtualNetworks = manager.getVirtualNetworks(TenantId.tenantId(tenantIdValue1));
         assertTrue("The virtual network set should be empty.", virtualNetworks.isEmpty());
 
+        // Create/remove a virtual network.
+        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
+        manager.removeVirtualNetwork(virtualNetwork.id());
+
+        virtualNetworks = manager.getVirtualNetworks(TenantId.tenantId(tenantIdValue1));
+        assertTrue("The virtual network set should be empty.", virtualNetworks.isEmpty());
+
         // Validate that the events were all received in the correct order.
         validateEvents(VirtualNetworkEvent.Type.TENANT_REGISTERED, VirtualNetworkEvent.Type.NETWORK_ADDED,
                        VirtualNetworkEvent.Type.NETWORK_ADDED, VirtualNetworkEvent.Type.NETWORK_REMOVED,
+                       VirtualNetworkEvent.Type.NETWORK_REMOVED, VirtualNetworkEvent.Type.NETWORK_ADDED,
                        VirtualNetworkEvent.Type.NETWORK_REMOVED);
     }
 
@@ -209,6 +222,13 @@
         virtualDevices1 = manager.getVirtualDevices(virtualNetwork1.id());
         assertTrue("The virtual device set should be empty.", virtualDevices1.isEmpty());
 
+        // Add/remove the virtual device again.
+        VirtualDevice virtualDevice = manager.createVirtualDevice(virtualNetwork1.id(),
+                                                                  DeviceId.deviceId(deviceIdValue1));
+        manager.removeVirtualDevice(virtualDevice.networkId(), virtualDevice.id());
+        virtualDevices1 = manager.getVirtualDevices(virtualNetwork1.id());
+        assertTrue("The virtual device set should be empty.", virtualDevices1.isEmpty());
+
         // Validate that the events were all received in the correct order.
         validateEvents(VirtualNetworkEvent.Type.TENANT_REGISTERED, VirtualNetworkEvent.Type.NETWORK_ADDED,
                        VirtualNetworkEvent.Type.NETWORK_ADDED);
@@ -241,6 +261,12 @@
         }
         virtualLinks = manager.getVirtualLinks(virtualNetwork1.id());
         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));
+        manager.removeVirtualLink(virtualLink.networkId(), virtualLink.src(), virtualLink.dst());
+        virtualLinks = manager.getVirtualLinks(virtualNetwork1.id());
+        assertTrue("The virtual link set should be empty.", virtualLinks.isEmpty());
     }
 
     /**
@@ -250,19 +276,18 @@
     public void testAddRemoveVirtualPort() {
         manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
         VirtualNetwork virtualNetwork1 = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
-        VirtualDevice srcVirtualDevice =
+        VirtualDevice virtualDevice =
                 manager.createVirtualDevice(virtualNetwork1.id(), DeviceId.deviceId(deviceIdValue1));
-        VirtualDevice dstVirtualDevice =
-                manager.createVirtualDevice(virtualNetwork1.id(), DeviceId.deviceId(deviceIdValue2));
-        Port port = new DefaultPort(srcVirtualDevice, PortNumber.portNumber(1), true);
+        Port port = new DefaultPort(virtualDevice, PortNumber.portNumber(1), true);
 
-        manager.createVirtualPort(virtualNetwork1.id(), srcVirtualDevice.id(), PortNumber.portNumber(1), port);
-        manager.createVirtualPort(virtualNetwork1.id(), dstVirtualDevice.id(), PortNumber.portNumber(1), port);
+        manager.createVirtualPort(virtualNetwork1.id(), virtualDevice.id(), PortNumber.portNumber(1), port);
+        manager.createVirtualPort(virtualNetwork1.id(), virtualDevice.id(), PortNumber.portNumber(2), port);
 
-        Set<VirtualPort> virtualPorts = manager.getVirtualPorts(virtualNetwork1.id(), srcVirtualDevice.id());
+        Set<VirtualPort> virtualPorts = manager.getVirtualPorts(virtualNetwork1.id(), virtualDevice.id());
         assertNotNull("The virtual port set should not be null", virtualPorts);
         assertEquals("The virtual port set size did not match.", 2, virtualPorts.size());
 
+
         for (VirtualPort virtualPort : virtualPorts) {
             manager.removeVirtualPort(virtualNetwork1.id(),
                                       (DeviceId) virtualPort.element().id(), virtualPort.number());
@@ -270,7 +295,14 @@
             manager.removeVirtualPort(virtualNetwork1.id(),
                                       (DeviceId) virtualPort.element().id(), virtualPort.number());
         }
-        virtualPorts = manager.getVirtualPorts(virtualNetwork1.id(), srcVirtualDevice.id());
+        virtualPorts = manager.getVirtualPorts(virtualNetwork1.id(), virtualDevice.id());
+        assertTrue("The virtual port set should be empty.", virtualPorts.isEmpty());
+
+        // Add/remove the virtual port again.
+        VirtualPort virtualPort = manager.createVirtualPort(virtualNetwork1.id(), virtualDevice.id(),
+                                                            PortNumber.portNumber(1), port);
+        manager.removeVirtualPort(virtualNetwork1.id(), (DeviceId) virtualPort.element().id(), virtualPort.number());
+        virtualPorts = manager.getVirtualPorts(virtualNetwork1.id(), virtualDevice.id());
         assertTrue("The virtual port set should be empty.", virtualPorts.isEmpty());
     }
 
@@ -306,6 +338,9 @@
 
     }
 
+    /**
+     * Core service test class.
+     */
     private class TestCoreService extends CoreServiceAdapter {
 
         @Override
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 65cee11..d4461a4 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
@@ -42,6 +42,8 @@
 import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
 import org.onosproject.incubator.net.virtual.VirtualPort;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultPort;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
@@ -123,11 +125,18 @@
                            .register(TenantId.class)
                            .register(NetworkId.class).register(DeviceId.class)
                            .register(VirtualNetwork.class)
+                           .register(DefaultVirtualNetwork.class)
                            .register(VirtualDevice.class)
+                           .register(DefaultVirtualDevice.class)
                            .register(VirtualLink.class)
+                           .register(DefaultVirtualLink.class)
                            .register(VirtualPort.class)
+                           .register(DefaultVirtualPort.class)
                            .register(DeviceId.class)
                            .register(Device.class)
+                           .register(TunnelId.class)
+                           .register(DefaultDevice.class)
+                           .register(DefaultPort.class)
                            .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID).build());
 
     /**
@@ -233,12 +242,14 @@
         VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
         //TODO update both maps in one transaction.
         networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
-        Set<NetworkId> virtualNetworkSet = tenantIdNetworkIdSetMap.get(tenantId);
-        if (virtualNetworkSet == null) {
-            virtualNetworkSet = new HashSet<>();
+
+        Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
+        if (networkIdSet == null) {
+            networkIdSet = new HashSet<>();
         }
-        virtualNetworkSet.add(virtualNetwork.id());
-        tenantIdNetworkIdSetMap.put(tenantId, virtualNetworkSet);
+        networkIdSet.add(virtualNetwork.id());
+        tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
+
         return virtualNetwork;
     }
 
@@ -256,24 +267,26 @@
     public void removeNetwork(NetworkId networkId) {
         // Make sure that the virtual network exists before attempting to remove it.
         if (networkExists(networkId)) {
-            VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.get(networkId);
+            //TODO update both maps in one transaction.
+
+            VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
             if (virtualNetwork == null) {
                 return;
             }
-            //TODO update both maps in one transaction.
             TenantId tenantId = virtualNetwork.tenantId();
-            networkIdVirtualNetworkMap.compute(networkId, (id, existingVirtualNetwork) -> null);
 
+            Set<NetworkId> networkIdSet = new HashSet<>();
+            tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
+                if (networkId1.id().equals(networkId.id())) {
+                    networkIdSet.add(networkId1);
+                }
+            });
 
-            Set<NetworkId> virtualNetworkSet = tenantIdNetworkIdSetMap.get(tenantId);
             tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
                 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
-                    return ImmutableSet.of();
+                    return new HashSet<NetworkId>();
                 } else {
-                    return ImmutableSet.<NetworkId>builder()
-                            .addAll(Sets.difference(existingNetworkIds,
-                                                    ImmutableSet.copyOf(virtualNetworkSet)))
-                            .build();
+                    return new HashSet<NetworkId>(Sets.difference(existingNetworkIds, networkIdSet));
                 }
             });
         }
@@ -308,22 +321,24 @@
     public void removeDevice(NetworkId networkId, DeviceId deviceId) {
         checkState(networkExists(networkId), "The network has not been added.");
         //TODO update both maps in one transaction.
-        Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
+
+        Set<DeviceId> deviceIdSet = new HashSet<>();
+        networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
+            if (deviceId1.equals(deviceId)) {
+                deviceIdSet.add(deviceId1);
+            }
+        });
+
         if (deviceIdSet != null) {
             networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
                 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
-                    return ImmutableSet.of();
+                    return new HashSet<DeviceId>();
                 } else {
-                    return ImmutableSet.<DeviceId>builder()
-                            .addAll(Sets.difference(existingDeviceIds,
-                                                    ImmutableSet.copyOf(deviceIdSet)))
-                            .build();
+                    return new HashSet<DeviceId>(Sets.difference(existingDeviceIds, deviceIdSet));
                 }
             });
 
-            deviceIdVirtualDeviceMap.compute(deviceId, (id, existingVirtualDevice) -> null);
-
-            log.info("The deviceIdVirtualDeviceMap size is: " + getDevices(networkId));
+            deviceIdVirtualDeviceMap.remove(deviceId);
         }
     }
 
@@ -343,16 +358,20 @@
     @Override
     public void removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
         checkState(networkExists(networkId), "The network has not been added.");
-        Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
+
+        Set<VirtualLink> virtualLinkSet = new HashSet<>();
+        networkIdVirtualLinkSetMap.get(networkId).forEach(link -> {
+            if (link.src().equals(src) && link.dst().equals(dst)) {
+                virtualLinkSet.add(link);
+            }
+        });
+
         if (virtualLinkSet != null) {
             networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
                 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
-                    return ImmutableSet.of();
+                    return new HashSet<VirtualLink>();
                 } else {
-                    return ImmutableSet.<VirtualLink>builder()
-                            .addAll(Sets.difference(existingVirtualLinks,
-                                                    ImmutableSet.copyOf(virtualLinkSet)))
-                            .build();
+                    return new HashSet<VirtualLink>(Sets.difference(existingVirtualLinks, virtualLinkSet));
                 }
             });
         }
@@ -376,16 +395,20 @@
     @Override
     public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
         checkState(networkExists(networkId), "The network has not been added.");
-        Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
+
+        Set<VirtualPort> virtualPortSet = new HashSet<>();
+        networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
+            if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
+                virtualPortSet.add(port);
+            }
+        });
+
         if (virtualPortSet != null) {
             networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
                 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
-                    return ImmutableSet.of();
+                    return new HashSet<VirtualPort>();
                 } else {
-                    return ImmutableSet.<VirtualPort>builder()
-                            .addAll(Sets.difference(existingVirtualPorts,
-                                                    ImmutableSet.copyOf(virtualPortSet)))
-                            .build();
+                    return new HashSet<VirtualPort>(Sets.difference(existingVirtualPorts, virtualPortSet));
                 }
             });
         }
@@ -415,17 +438,28 @@
     @Override
     public Set<VirtualLink> getLinks(NetworkId networkId) {
         checkState(networkExists(networkId), "The network has not been added.");
-        Set<VirtualLink> virtualLinkSet = new HashSet<>();
-        virtualLinkSet.addAll(networkIdVirtualLinkSetMap.get(networkId));
+        Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
+        if (virtualLinkSet == null) {
+            virtualLinkSet = new HashSet<>();
+        }
         return ImmutableSet.copyOf(virtualLinkSet);
     }
 
     @Override
     public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
         checkState(networkExists(networkId), "The network has not been added.");
-        Set<VirtualPort> virtualPortSet = new HashSet<>();
-        virtualPortSet.addAll(networkIdVirtualPortSetMap.get(networkId));
-        return ImmutableSet.copyOf(virtualPortSet);
+        Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
+        if (virtualPortSet == null) {
+            virtualPortSet = new HashSet<>();
+        }
+
+        Set<VirtualPort> portSet = new HashSet<>();
+        virtualPortSet.forEach(virtualPort -> {
+            if (virtualPort.element().id().equals(deviceId)) {
+                portSet.add(virtualPort);
+            }
+        });
+        return ImmutableSet.copyOf(portSet);
     }
 
     /**