Starting work on virtual network subsystem implementation.

Change-Id: Ic702ce425d68fa5c1af5c6d55cad5940665ac562
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualDevice.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualDevice.java
new file mode 100644
index 0000000..54a22a4
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualDevice.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 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;
+
+import org.onlab.packet.ChassisId;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.*;
+
+/**
+ * Default representation of a virtual device.
+ */
+public class DefaultVirtualDevice extends DefaultDevice implements VirtualDevice {
+
+    private static final String VIRTUAL = "virtual";
+    private static final ProviderId PID = new ProviderId(VIRTUAL, VIRTUAL);
+
+    private final NetworkId networkId;
+
+    /**
+     * Creates a network element attributed to the specified provider.
+     *
+     * @param networkId network identifier
+     * @param id        device identifier
+     */
+    public DefaultVirtualDevice(NetworkId networkId, DeviceId id) {
+        super(PID, id, Type.VIRTUAL, VIRTUAL, VIRTUAL, VIRTUAL, VIRTUAL,
+              new ChassisId(0));
+        this.networkId = networkId;
+    }
+
+    @Override
+    public NetworkId networkId() {
+        return networkId;
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 * super.hashCode() + Objects.hash(networkId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DefaultVirtualDevice) {
+            DefaultVirtualDevice that = (DefaultVirtualDevice) obj;
+            return super.equals(that) && Objects.equals(this.networkId, that.networkId);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this).add("networkId", networkId).toString();
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetwork.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetwork.java
new file mode 100644
index 0000000..c114191
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetwork.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 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;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of the virtual network descriptor.
+ */
+public class DefaultVirtualNetwork implements VirtualNetwork {
+
+    private final NetworkId id;
+    private final TenantId tenantId;
+
+    /**
+     * Creates a new virtual network descriptor.
+     *
+     * @param id       network identifier
+     * @param tenantId tenant identifier
+     */
+    public DefaultVirtualNetwork(NetworkId id, TenantId tenantId) {
+        this.id = id;
+        this.tenantId = tenantId;
+    }
+
+    @Override
+    public NetworkId id() {
+        return id;
+    }
+
+    @Override
+    public TenantId tenantId() {
+        return tenantId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, tenantId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DefaultVirtualNetwork) {
+            DefaultVirtualNetwork that = (DefaultVirtualNetwork) obj;
+            return Objects.equals(this.id, that.id)
+                    && Objects.equals(this.tenantId, that.tenantId);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("id", id)
+                .add("tenantId", tenantId)
+                .toString();
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualElement.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualElement.java
index 1c74b92..791b8e2 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualElement.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualElement.java
@@ -24,13 +24,6 @@
 public interface VirtualElement {
 
     /**
-     * Returns the identifier of the tenant to which this virtual element belongs.
-     *
-     * @return tenant identifier
-     */
-    TenantId tenantId();
-
-    /**
      * Returns the network identifier to which this virtual element belongs.
      *
      * @return network identifier
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 1e3648b..07c399c 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,14 +16,11 @@
 package org.onosproject.incubator.net.virtual;
 
 import com.google.common.annotations.Beta;
-import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceDescription;
-import org.onosproject.net.device.PortDescription;
-import org.onosproject.net.link.LinkDescription;
 
 import java.util.Set;
 
@@ -76,12 +73,12 @@
      * Creates a new virtual device within the specified network. The device id
      * must be unique within the bounds of the network.
      *
-     * @param networkId   network identifier
-     * @param description device description
+     * @param networkId network identifier
+     * @param deviceId  device identifier
      * @return newly created device
      * @throws org.onlab.util.ItemNotFoundException if no such network found
      */
-    VirtualDevice createVirtualDevice(NetworkId networkId, DeviceDescription description);
+    VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId);
 
     /**
      * Removes the specified virtual device and all its ports and affiliated links.
@@ -96,14 +93,16 @@
     /**
      * Creates a new virtual link within the specified network.
      *
-     * @param networkId   network identifier
-     * @param description link description
-     * @param realizedBy  tunnel using which this link is realized
+     * @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, LinkDescription description,
-                                  Tunnel realizedBy);
+    VirtualLink createVirtualLink(NetworkId networkId,
+                                  ConnectPoint src, ConnectPoint dst,
+                                  TunnelId realizedBy);
 
     // TODO: Discuss whether we should provide an alternate createVirtualLink
     // which is backed by a Path instead; I'm leaning towards not doing that.
@@ -119,20 +118,17 @@
     void removeVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
 
     /**
-     * Creates a new virtual port on the specified device. Note that the port
-     * description can only request the resources which the underlying port
-     * port is capable of providing. It is, however, permissible to request
-     * only portion of those resources.
+     * Creates a new virtual port on the specified device.
      *
-     * @param networkId   network identifier
-     * @param deviceId    device identifier
-     * @param description port description
-     * @param realizedBy  underlying port using which this virtual port is realized
+     * @param networkId  network identifier
+     * @param deviceId   device identifier
+     * @param portNumber port number
+     * @param realizedBy underlying port using which this virtual port is realized
      * @return newly created port
      * @throws org.onlab.util.ItemNotFoundException if no such network or device found
      */
     VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
-                                  PortDescription description, Port realizedBy);
+                                  PortNumber portNumber, Port realizedBy);
 
     /**
      * Removes the specified virtual port.
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java
new file mode 100644
index 0000000..7e076e0
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2015 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;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes virtual network event.
+ */
+public class VirtualNetworkEvent extends AbstractEvent<VirtualNetworkEvent.Type, NetworkId> {
+
+    /**
+     * Type of virtual network events.
+     */
+    public enum Type {
+        /**
+         * Signifies that a new tenant identifier was registered.
+         */
+        TENANT_REGISTERED,
+        /**
+         * Signifies that a tenant identifier was unregistered.
+         */
+        TENANT_UNREGISTERED,
+        /**
+         * Signifies that a new virtual network was added.
+         */
+        NETWORK_ADDED,
+        /**
+         * Signifies that a virtual network was updated.
+         */
+        NETWORK_UPDATED,
+        /**
+         * Signifies that a virtual network was removed.
+         */
+        NETWORK_REMOVED
+    }
+
+    /**
+     * Creates an event of a given type and for the specified subject and the
+     * current time.
+     *
+     * @param type        event type
+     * @param subject     event subject
+     */
+    public VirtualNetworkEvent(Type type, NetworkId subject) {
+        super(type, subject);
+    }
+
+    /**
+     * Creates an event of a given type and for the specified subject and time.
+     *
+     * @param type        device event type
+     * @param subject     event subject
+     * @param time        occurrence time
+     */
+    public VirtualNetworkEvent(Type type, NetworkId subject, long time) {
+        super(type, subject, time);
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkListener.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkListener.java
new file mode 100644
index 0000000..707ca8a
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 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;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Represents entity capable of receiving virtual network events.
+ */
+public interface VirtualNetworkListener extends EventListener<VirtualNetworkEvent> {
+}
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
new file mode 100644
index 0000000..49ad2f2
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2015 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;
+
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Mechanism for distributing and storing virtual network model information.
+ */
+public interface VirtualNetworkStore
+        extends Store<VirtualNetworkEvent, VirtualNetworkStoreDelegate> {
+
+    /**
+     * Adds a new tenant ID to the store.
+     *
+     * @param tenantId tenant identifier
+     */
+    void addTenantId(TenantId tenantId);
+
+    /**
+     * Removes the specified tenant ID from the store.
+     *
+     * @param tenantId tenant identifier
+     */
+    void removeTenantId(TenantId tenantId);
+
+    /**
+     * Returns set of registered tenant IDs.
+     *
+     * @return set of tenant identifiers
+     */
+    Set<TenantId> getTenantIds();
+
+    /**
+     * Adds a new virtual network for the specified tenant to the store.
+     *
+     * @param tenantId tenant identifier
+     * @return the virtual network
+     */
+    VirtualNetwork addNetwork(TenantId tenantId);
+
+    /**
+     * Removes the specified virtual network from the store.
+     *
+     * @param networkId network identifier
+     */
+    void removeNetwork(NetworkId networkId);
+
+    /**
+     * Adds a new virtual device to the store. This device will have no ports.
+     *
+     * @param networkId network identifier
+     * @param deviceId  device identifier
+     * @return the virtual device
+     */
+    VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId);
+
+    /**
+     * Renmoves the specified virtual device from the given network.
+     *
+     * @param networkId network identifier
+     * @param deviceId  device identifier
+     */
+    void removeDevice(NetworkId networkId, DeviceId deviceId);
+
+    /**
+     * Adds a new virtual link.
+     *
+     * @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
+     * @return the virtual link
+     */
+    VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
+                        TunnelId realizedBy);
+
+    /**
+     * Removes the specified link from the store.
+     *
+     * @param networkId network identifier
+     * @param src       source connection point
+     * @param dst       destination connection point
+     */
+    void removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
+
+    /**
+     * Adds a new virtual port to the network.
+     *
+     * @param networkId  network identifier
+     * @param deviceId   device identifier
+     * @param portNumber port number
+     * @param realizedBy underlying port which realizes the virtual port
+     * @return the virtual port
+     */
+    VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
+                        PortNumber portNumber, Port realizedBy);
+
+    /**
+     * Removes the specified port from the given device and network.
+     *
+     * @param networkId  network identifier
+     * @param deviceId   device identifier
+     * @param portNumber port number
+     */
+    void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber);
+
+    /**
+     * Returns the list of networks.
+     *
+     * @param tenantId tenant identifier
+     * @return set of virtual networks
+     */
+    Set<VirtualNetwork> getNetworks(TenantId tenantId);
+
+    /**
+     * Returns the list of devices in the specified virtual network.
+     *
+     * @param networkId network identifier
+     * @return set of virtual devices
+     */
+    Set<VirtualDevice> getDevices(NetworkId networkId);
+
+    /**
+     * Returns the list of virtual links in the specified virtual network.
+     *
+     * @param networkId network identifier
+     * @return set of virtual links
+     */
+    Set<VirtualLink> getLinks(NetworkId networkId);
+
+    /**
+     * Returns the list of ports of the specified virtual device.
+     *
+     * @param networkId network identifier
+     * @param deviceId   device identifier
+     * @return set of virtual networks
+     */
+    Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId);
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStoreDelegate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStoreDelegate.java
new file mode 100644
index 0000000..e57c3d3
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 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;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Network configuration store delegate abstraction.
+ */
+public interface VirtualNetworkStoreDelegate extends StoreDelegate<VirtualNetworkEvent> {
+}
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
new file mode 100644
index 0000000..55bb630
--- /dev/null
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2015 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.event.AbstractListenerManager;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualLink;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
+import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
+import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
+import org.onosproject.incubator.net.virtual.VirtualPort;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Implementation of the virtual network service.
+ */
+@Component(immediate = true)
+@Service
+public class VirtualNetworkManager
+        extends AbstractListenerManager<VirtualNetworkEvent, VirtualNetworkListener>
+        implements VirtualNetworkService, VirtualNetworkAdminService {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private static final String TENANT_NULL = "Tenant ID cannot be null";
+    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";
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected VirtualNetworkStore store;
+
+    private VirtualNetworkStoreDelegate delegate = new InternalStoreDelegate();
+
+    // TODO: figure out how to coordinate "implementation" of a virtual network
+
+    @Activate
+    protected void activate() {
+        store.setDelegate(delegate);
+        log.info("Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        store.unsetDelegate(delegate);
+        log.info("Stopped");
+    }
+
+    @Override
+    public void registerTenantId(TenantId tenantId) {
+        checkNotNull(tenantId, TENANT_NULL);
+        store.addTenantId(tenantId);
+    }
+
+    @Override
+    public void unregisterTenantId(TenantId tenantId) {
+        checkNotNull(tenantId, TENANT_NULL);
+        store.removeTenantId(tenantId);
+    }
+
+    @Override
+    public Set<TenantId> getTenantIds() {
+        return store.getTenantIds();
+    }
+
+    @Override
+    public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
+        checkNotNull(tenantId, TENANT_NULL);
+        return store.addNetwork(tenantId);
+    }
+
+    @Override
+    public void removeVirtualNetwork(NetworkId networkId) {
+        checkNotNull(networkId, NETWORK_NULL);
+        store.removeNetwork(networkId);
+    }
+
+    @Override
+    public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
+        checkNotNull(networkId, NETWORK_NULL);
+        checkNotNull(deviceId, DEVICE_NULL);
+        return store.addDevice(networkId, deviceId);
+    }
+
+    @Override
+    public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
+        checkNotNull(networkId, NETWORK_NULL);
+        checkNotNull(deviceId, DEVICE_NULL);
+        store.removeDevice(networkId, deviceId);
+    }
+
+    @Override
+    public VirtualLink createVirtualLink(NetworkId networkId,
+                                         ConnectPoint src, ConnectPoint dst,
+                                         TunnelId realizedBy) {
+        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);
+    }
+
+    @Override
+    public void removeVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
+        checkNotNull(networkId, NETWORK_NULL);
+        checkNotNull(src, LINK_POINT_NULL);
+        checkNotNull(dst, LINK_POINT_NULL);
+        store.removeLink(networkId, src, dst);
+    }
+
+    @Override
+    public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
+                                         PortNumber portNumber, Port realizedBy) {
+        checkNotNull(networkId, NETWORK_NULL);
+        checkNotNull(deviceId, DEVICE_NULL);
+        checkNotNull(portNumber, "Port description cannot be null");
+        return store.addPort(networkId, deviceId, portNumber, realizedBy);
+    }
+
+    @Override
+    public void removeVirtualPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
+        checkNotNull(networkId, NETWORK_NULL);
+        checkNotNull(deviceId, DEVICE_NULL);
+        checkNotNull(portNumber, "Port number cannot be null");
+        store.removePort(networkId, deviceId, portNumber);
+    }
+
+    @Override
+    public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
+        checkNotNull(tenantId, TENANT_NULL);
+        return store.getNetworks(tenantId);
+    }
+
+    @Override
+    public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
+        checkNotNull(networkId, NETWORK_NULL);
+        return store.getDevices(networkId);
+    }
+
+    @Override
+    public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
+        checkNotNull(networkId, NETWORK_NULL);
+        return store.getLinks(networkId);
+    }
+
+    @Override
+    public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
+        checkNotNull(networkId, NETWORK_NULL);
+        checkNotNull(deviceId, DEVICE_NULL);
+        return store.getPorts(networkId, deviceId);
+    }
+
+    @Override
+    public <T> T get(NetworkId networkId, Class<T> serviceClass) {
+        checkNotNull(networkId, NETWORK_NULL);
+        return null;
+    }
+
+    // Auxiliary store delegate to receive notification about changes in
+    // the virtual network configuration store state - by the store itself.
+    private class InternalStoreDelegate implements VirtualNetworkStoreDelegate {
+        @Override
+        public void notify(VirtualNetworkEvent event) {
+            post(event);
+        }
+    }
+
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/package-info.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/package-info.java
new file mode 100644
index 0000000..da4be5a
--- /dev/null
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/**
+ * Implementation of the virtual network subsystem.
+ */
+package org.onosproject.incubator.net.virtual.impl;
\ No newline at end of file
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
new file mode 100644
index 0000000..69e56c0
--- /dev/null
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2015 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.store.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.Service;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
+import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualLink;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
+import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
+import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
+import org.onosproject.incubator.net.virtual.VirtualPort;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.store.AbstractStore;
+import org.slf4j.Logger;
+
+import java.util.Set;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of the network store.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedVirtualNetworkStore
+        extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
+        implements VirtualNetworkStore {
+
+    private final Logger log = getLogger(getClass());
+
+    // TODO: track tenants by ID
+    // TODO: track networks by ID and by tenants
+    // TODO: track devices by network ID and device ID
+    // TODO: track devices by network ID
+    // TODO: setup block allocator for network IDs
+
+    // TODO: notify delegate
+
+    @Activate
+    public void activate() {
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        log.info("Stopped");
+    }
+
+    @Override
+    public void addTenantId(TenantId tenantId) {
+    }
+
+    @Override
+    public void removeTenantId(TenantId tenantId) {
+    }
+
+    @Override
+    public Set<TenantId> getTenantIds() {
+        return null;
+    }
+
+    @Override
+    public VirtualNetwork addNetwork(TenantId tenantId) {
+        return new DefaultVirtualNetwork(genNetworkId(), tenantId);
+    }
+
+    private NetworkId genNetworkId() {
+        return NetworkId.networkId(0); // TODO: use a block allocator
+    }
+
+
+    @Override
+    public void removeNetwork(NetworkId networkId) {
+    }
+
+    @Override
+    public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
+        return new DefaultVirtualDevice(networkId, deviceId);
+    }
+
+    @Override
+    public void removeDevice(NetworkId networkId, DeviceId deviceId) {
+    }
+
+    @Override
+    public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId realizedBy) {
+        return null;
+    }
+
+    @Override
+    public void removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
+    }
+
+    @Override
+    public VirtualPort addPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber, Port realizedBy) {
+        return null;
+    }
+
+    @Override
+    public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
+    }
+
+    @Override
+    public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
+        return null;
+    }
+
+    @Override
+    public Set<VirtualDevice> getDevices(NetworkId networkId) {
+        return null;
+    }
+
+    @Override
+    public Set<VirtualLink> getLinks(NetworkId networkId) {
+        return null;
+    }
+
+    @Override
+    public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
+        return null;
+    }
+}
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/package-info.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/package-info.java
new file mode 100644
index 0000000..12fa909
--- /dev/null
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 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.
+ */
+
+/**
+ * Implementation of distributed virtual network store.
+ */
+package org.onosproject.incubator.store.virtual.impl;