Detangling incubator: virtual nets, tunnels, resource labels, oh my
- virtual networking moved to /apps/virtual; with CLI & REST API
- tunnels and labels moved to /apps/tunnel; with CLI & REST API; UI disabled for now
- protobuf/models moved to /core/protobuf/models
- defunct grpc/rpc registry stuff left under /graveyard
- compile dependencies on /incubator moved to respective modules for compilation
- run-time dependencies will need to be re-tested for dependent apps
- /graveyard will be removed in not-too-distant future
Change-Id: I0a0b995c635487edcf95a352f50dd162186b0b39
diff --git a/apps/virtual/api/BUILD b/apps/virtual/api/BUILD
new file mode 100644
index 0000000..da7ca40
--- /dev/null
+++ b/apps/virtual/api/BUILD
@@ -0,0 +1,11 @@
+COMPILE_DEPS = CORE_DEPS + JACKSON + [
+ "//apps/tunnel/api:onos-apps-tunnel-api",
+]
+
+TEST_DEPS = TEST_ADAPTERS
+
+osgi_jar_with_tests(
+ test_deps = TEST_DEPS,
+ visibility = ["//visibility:public"],
+ deps = COMPILE_DEPS,
+)
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/AbstractVnetService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/AbstractVnetService.java
new file mode 100644
index 0000000..b3e1d18
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/AbstractVnetService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.osgi.ServiceDirectory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Basis for virtual network service.
+ */
+public abstract class AbstractVnetService
+ implements VnetService {
+
+ private static final String NETWORK_NULL = "Network ID cannot be null";
+
+ protected NetworkId networkId;
+ protected VirtualNetworkService manager;
+ protected ServiceDirectory serviceDirectory;
+
+ public AbstractVnetService(VirtualNetworkService manager,
+ NetworkId networkId) {
+ checkNotNull(networkId, NETWORK_NULL);
+ this.manager = manager;
+ this.networkId = networkId;
+ this.serviceDirectory = manager.getServiceDirectory();
+ }
+
+ @Override
+ public NetworkId networkId() {
+ return this.networkId;
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/Comparators.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/Comparators.java
new file mode 100644
index 0000000..8c67e00
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/Comparators.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.Comparator;
+
+/**
+ * Various comparators.
+ */
+public final class Comparators {
+
+ // Ban construction
+ private Comparators() {
+ }
+
+ public static final Comparator<VirtualNetwork> VIRTUAL_NETWORK_COMPARATOR =
+ (v1, v2) -> {
+ int compareId = v1.tenantId().toString().compareTo(v2.tenantId().toString());
+ return (compareId != 0) ? compareId : Long.signum(v1.id().id() - v2.id().id());
+ };
+
+ public static final Comparator<VirtualDevice> VIRTUAL_DEVICE_COMPARATOR =
+ (v1, v2) -> v1.id().toString().compareTo(v2.id().toString());
+
+ public static final Comparator<VirtualPort> VIRTUAL_PORT_COMPARATOR =
+ (v1, v2) -> v1.number().toString().compareTo(v2.number().toString());
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualDevice.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualDevice.java
new file mode 100644
index 0000000..98e3e1e
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualDevice.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 final 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 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/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualHost.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualHost.java
new file mode 100644
index 0000000..61f31b1
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualHost.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultHost;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default representation of a virtual host.
+ */
+public final class DefaultVirtualHost extends DefaultHost implements VirtualHost {
+
+ private static final String VIRTUAL = "virtual";
+ private static final ProviderId PID = new ProviderId(VIRTUAL, VIRTUAL);
+
+ private final NetworkId networkId;
+
+ /**
+ * Creates a virtual host attributed to the specified provider.
+ *
+ * @param networkId network identifier
+ * @param id host identifier
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param location host location
+ * @param ips host IP addresses
+ */
+ public DefaultVirtualHost(NetworkId networkId, HostId id, MacAddress mac,
+ VlanId vlan, HostLocation location, Set<IpAddress> ips) {
+ this(networkId, id, mac, vlan, Collections.singleton(location), ips);
+ }
+
+ /**
+ * Creates a virtual host attributed to the specified provider.
+ *
+ * @param networkId network identifier
+ * @param id host identifier
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param locations host locations
+ * @param ips host IP addresses
+ */
+ public DefaultVirtualHost(NetworkId networkId, HostId id, MacAddress mac,
+ VlanId vlan, Set<HostLocation> locations, Set<IpAddress> ips) {
+ super(PID, id, mac, vlan, locations, ips, false, DefaultAnnotations.builder().build());
+ this.networkId = networkId;
+ }
+
+ @Override
+ public NetworkId networkId() {
+ return networkId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(networkId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultVirtualHost) {
+ DefaultVirtualHost that = (DefaultVirtualHost) 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/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualLink.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualLink.java
new file mode 100644
index 0000000..20924bc
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualLink.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.DefaultAnnotations;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default representation of a virtual link.
+ */
+public final class DefaultVirtualLink extends DefaultLink implements VirtualLink {
+
+ private static final String VIRTUAL = "virtualLink";
+ public static final ProviderId PID = new ProviderId(VIRTUAL, VIRTUAL);
+
+ private final NetworkId networkId;
+ private final TunnelId tunnelId;
+
+ /**
+ * Private constructor for a default virtual link.
+ *
+ * @param networkId network identifier
+ * @param src source connection point
+ * @param dst destination connection point
+ * @param state link state
+ * @param tunnelId tunnel identifier
+ */
+ private DefaultVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
+ State state, TunnelId tunnelId) {
+ super(PID, src, dst, Type.VIRTUAL, state, DefaultAnnotations.builder().build());
+ this.networkId = networkId;
+ this.tunnelId = tunnelId;
+ }
+
+ @Override
+ public NetworkId networkId() {
+ return networkId;
+ }
+
+ /**
+ * Returns the tunnel identifier.
+ *
+ * @return tunnel identifier.
+ */
+ public TunnelId tunnelId() {
+ return tunnelId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(networkId, tunnelId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultVirtualLink) {
+ DefaultVirtualLink that = (DefaultVirtualLink) obj;
+ return super.equals(that) &&
+ Objects.equals(this.networkId, that.networkId) &&
+ Objects.equals(this.tunnelId, that.tunnelId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("networkId", networkId).add("tunnelId", tunnelId).toString();
+ }
+
+ /**
+ * Creates a new default virtual link builder.
+ *
+ * @return default virtual link builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder for DefaultVirtualLink objects.
+ */
+ public static final class Builder extends DefaultLink.Builder {
+ private NetworkId networkId;
+ private ConnectPoint src;
+ private ConnectPoint dst;
+ private TunnelId tunnelId;
+ private State state;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ /**
+ * Sets the network identifier to be used by the builder.
+ *
+ * @param networkId network identifier
+ * @return self
+ */
+ public Builder networkId(NetworkId networkId) {
+ this.networkId = networkId;
+ return this;
+ }
+
+ /**
+ * Sets the source connect point to be used by the builder.
+ *
+ * @param src source connect point
+ * @return self
+ */
+ public Builder src(ConnectPoint src) {
+ this.src = src;
+ return this;
+ }
+
+ /**
+ * Sets the destination connect point to be used by the builder.
+ *
+ * @param dst new destination connect point
+ * @return self
+ */
+ public Builder dst(ConnectPoint dst) {
+ this.dst = dst;
+ return this;
+ }
+
+ /**
+ * Sets the tunnel identifier to be used by the builder.
+ *
+ * @param tunnelId tunnel identifier
+ * @return self
+ */
+ public Builder tunnelId(TunnelId tunnelId) {
+ this.tunnelId = tunnelId;
+ return this;
+ }
+
+ /**
+ * Sets the link state to be used by the builder.
+ *
+ * @param state link state
+ * @return self
+ */
+ public Builder state(State state) {
+ this.state = state;
+ return this;
+ }
+
+ /**
+ * Builds a default virtual link object from the accumulated parameters.
+ *
+ * @return default virtual link object
+ */
+ public DefaultVirtualLink build() {
+ checkNotNull(src, "Source connect point cannot be null");
+ checkNotNull(dst, "Destination connect point cannot be null");
+ checkNotNull(networkId, "Network Id cannot be null");
+
+ return new DefaultVirtualLink(networkId, src, dst, state, tunnelId);
+ }
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetwork.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetwork.java
new file mode 100644
index 0000000..bf7de57
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetwork.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.TenantId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of the virtual network descriptor.
+ */
+public final 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/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualPort.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualPort.java
new file mode 100644
index 0000000..d5f3efb
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/DefaultVirtualPort.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultPort;
+import org.onosproject.net.Device;
+import org.onosproject.net.Element;
+import org.onosproject.net.PortNumber;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default representation of a virtual port.
+ */
+public final class DefaultVirtualPort extends DefaultPort implements VirtualPort {
+
+ private final NetworkId networkId;
+ private final ConnectPoint realizedBy;
+
+ /**
+ * Creates a virtual port.
+ *
+ * @param networkId network identifier
+ * @param device parent network element
+ * @param portNumber port number
+ * @param realizedBy underling port which realizes this virtual port
+ */
+ public DefaultVirtualPort(NetworkId networkId, Device device, PortNumber portNumber,
+ ConnectPoint realizedBy) {
+ this(networkId, device, portNumber, false, realizedBy);
+ }
+
+ /**
+ * Creates a virtual port.
+ *
+ * @param networkId network identifier
+ * @param device parent network element
+ * @param portNumber port number
+ * @param isEnabled indicator whether the port is up and active
+ * @param realizedBy underling port which realizes this virtual port
+ */
+ public DefaultVirtualPort(NetworkId networkId, Device device, PortNumber portNumber,
+ boolean isEnabled, ConnectPoint realizedBy) {
+ super((Element) device, portNumber, isEnabled, DefaultAnnotations.builder().build());
+ this.networkId = networkId;
+ this.realizedBy = realizedBy;
+ }
+
+ /**
+ * Returns network identifier.
+ *
+ * @return network identifier
+ */
+ public NetworkId networkId() {
+ return networkId;
+ }
+
+ @Override
+ public ConnectPoint realizedBy() {
+ return realizedBy;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(networkId, realizedBy);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultVirtualPort) {
+ DefaultVirtualPort that = (DefaultVirtualPort) obj;
+ return super.equals(that) &&
+ Objects.equals(this.networkId, that.networkId) &&
+ Objects.equals(this.number(), that.number()) &&
+ Objects.equals(this.realizedBy, that.realizedBy);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("networkId", networkId).add("realizedBy", realizedBy).toString();
+ }
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/NetworkId.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/NetworkId.java
new file mode 100644
index 0000000..552e941
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/NetworkId.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onlab.util.Identifier;
+
+import java.util.Objects;
+
+/**
+ * Representation of network identity.
+ */
+@Beta
+public final class NetworkId extends Identifier<Long> {
+
+ /**
+ * Represents no network, or an unspecified network.
+ */
+ public static final NetworkId NONE = networkId(-1L);
+
+ /**
+ * Represents the underlying physical network.
+ */
+ public static final NetworkId PHYSICAL = networkId(0L);
+
+ /**
+ * Checks if the id is for virtual network.
+ *
+ * @return true if the id is for virtual network.
+ */
+ public final boolean isVirtualNetworkId() {
+ return (!Objects.equals(this, NONE) && !Objects.equals(this, PHYSICAL));
+ }
+
+ // Public construction is prohibited
+ private NetworkId(long id) {
+ super(id);
+ }
+
+
+ // Default constructor for serialization
+ protected NetworkId() {
+ super(-1L);
+ }
+
+ /**
+ * Creates a network id using the supplied backing id.
+ *
+ * @param id network id
+ * @return network identifier
+ */
+ public static NetworkId networkId(long id) {
+ return new NetworkId(id);
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualDevice.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualDevice.java
new file mode 100644
index 0000000..d4b098f
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualDevice.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onosproject.net.Device;
+
+/**
+ * Abstraction of a virtual device.
+ */
+@Beta
+public interface VirtualDevice extends VirtualElement, Device {
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualElement.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualElement.java
new file mode 100644
index 0000000..572d02d
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualElement.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+
+/**
+ * Abstraction of a virtual element.
+ */
+@Beta
+public interface VirtualElement {
+
+ /**
+ * Returns the network identifier to which this virtual element belongs.
+ *
+ * @return network identifier
+ */
+ NetworkId networkId();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualHost.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualHost.java
new file mode 100644
index 0000000..569d8e3
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualHost.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onosproject.net.Host;
+
+/**
+ * Abstraction of a virtual end-station host.
+ */
+@Beta
+public interface VirtualHost extends VirtualElement, Host {
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualLink.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualLink.java
new file mode 100644
index 0000000..6f68961
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualLink.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.net.Link;
+
+/**
+ * Abstraction of a virtual link.
+ */
+@Beta
+public interface VirtualLink extends VirtualElement, Link {
+ /**
+ * Returns the tunnel identifier to which this virtual link belongs.
+ *
+ * @return tunnel identifier
+ */
+ TunnelId tunnelId();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetwork.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetwork.java
new file mode 100644
index 0000000..1cbbddb
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetwork.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onosproject.net.TenantId;
+
+/**
+ * Representation of a virtual network.
+ */
+@Beta
+public interface VirtualNetwork {
+
+ /**
+ * Returns the network identifier.
+ *
+ * @return network id
+ */
+ NetworkId id();
+
+ /**
+ * Returns the identifier of the tenant to which this virtual network belongs.
+ *
+ * @return tenant identifier
+ */
+ TenantId tenantId();
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkAdminService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkAdminService.java
new file mode 100644
index 0000000..bade4078
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkAdminService.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.TenantId;
+
+import java.util.Set;
+
+/**
+ * Service for managing the inventory of virtual networks.
+ */
+@Beta
+public interface VirtualNetworkAdminService extends VirtualNetworkService {
+
+ /**
+ * Registers the specified, externally generated tenant identifier.
+ *
+ * @param tenantId tenant identifier
+ */
+ void registerTenantId(TenantId tenantId);
+
+ /**
+ * Unregisters the specified, externally generated tenant identifier.
+ *
+ * @param tenantId tenant identifier
+ * @throws IllegalStateException if there are networks still owned by this tenant
+ */
+ void unregisterTenantId(TenantId tenantId);
+
+ /**
+ * Returns the set of tenant identifiers known to the system.
+ *
+ * @return set of known tenant identifiers
+ */
+ Set<TenantId> getTenantIds();
+
+ /**
+ * Creates a new virtual network for the specified tenant.
+ *
+ * @param tenantId tenant identifier
+ * @return newly created virtual network
+ */
+ VirtualNetwork createVirtualNetwork(TenantId tenantId);
+
+ /**
+ * Removes the specified virtual network and all its devices and links.
+ *
+ * @param networkId network identifier
+ */
+ void removeVirtualNetwork(NetworkId networkId);
+
+ /**
+ * 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 deviceId device identifier
+ * @return newly created virtual device
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Removes the specified virtual device and all its ports and affiliated links.
+ *
+ * @param networkId network identifier
+ * @param deviceId device identifier
+ * @throws org.onlab.util.ItemNotFoundException if no such network or device found
+ */
+ void removeVirtualDevice(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Creates a new virtual host within the specified network. The host id
+ * must be unique within the bounds of the network.
+ *
+ * @param networkId network identifier
+ * @param hostId host identifier
+ * @param mac mac address
+ * @param vlan vlan identifier
+ * @param location host location
+ * @param ips set of ip addresses
+ * @return newly created virtual host
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ VirtualHost createVirtualHost(NetworkId networkId, HostId hostId, MacAddress mac,
+ VlanId vlan, HostLocation location, Set<IpAddress> ips);
+
+ /**
+ * Removes the specified virtual host.
+ *
+ * @param networkId network identifier
+ * @param hostId host identifier
+ * @throws org.onlab.util.ItemNotFoundException if no such network or host found
+ */
+ void removeVirtualHost(NetworkId networkId, HostId hostId);
+
+ /**
+ * Creates a new virtual link within the specified network.
+ *
+ * @param networkId network identifier
+ * @param src source connection point
+ * @param dst destination connection point
+ * @return newly created virtual link
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ VirtualLink createVirtualLink(NetworkId networkId,
+ ConnectPoint src, ConnectPoint dst);
+
+ // TODO: Discuss whether we should provide an alternate createVirtualLink
+ // which is backed by a Path instead; I'm leaning towards not doing that.
+
+ /**
+ * Removes the specified virtual link.
+ *
+ * @param networkId network identifier
+ * @param src source connection point
+ * @param dst destination connection point
+ * @throws org.onlab.util.ItemNotFoundException if no such network or link found
+ */
+ void removeVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
+
+ /**
+ * Creates a new virtual port on the specified device.
+ *
+ * @param networkId network identifier
+ * @param deviceId virtual device identifier
+ * @param portNumber virtual port number
+ * @param realizedBy underlying physical port using which this virtual port is realized
+ * @return newly created port
+ * @throws org.onlab.util.ItemNotFoundException if no such network or device is found
+ */
+ VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
+ PortNumber portNumber, ConnectPoint realizedBy);
+
+ /**
+ * Binds an existing virtual port on the specified device.
+ *
+ * @param networkId network identifier
+ * @param deviceId virtual device identifier
+ * @param portNumber virtual port number
+ * @param realizedBy underlying physical port using which this virtual port is realized
+ * @throws org.onlab.util.ItemNotFoundException if no such network or device is found
+ */
+ void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
+ PortNumber portNumber, ConnectPoint realizedBy);
+
+ /**
+ * Updates port state of an existing virtual port on the specified device.
+ *
+ * @param networkId network identifier
+ * @param deviceId virtual device identifier
+ * @param portNumber virtual port number
+ * @param isEnabled indicator whether the port is up and active
+ * @throws org.onlab.util.ItemNotFoundException if no such network or device is found
+ */
+ void updatePortState(NetworkId networkId, DeviceId deviceId,
+ PortNumber portNumber, boolean isEnabled);
+
+ /**
+ * Removes the specified virtual port.
+ *
+ * @param networkId network identifier
+ * @param deviceId device identifier
+ * @param portNumber port number
+ * @throws org.onlab.util.ItemNotFoundException if no such network or port found
+ */
+ void removeVirtualPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java
new file mode 100644
index 0000000..3f96496
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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,
+ /**
+ * Signifies that a new virtual network device was added.
+ */
+ VIRTUAL_DEVICE_ADDED,
+ /**
+ * Signifies that a virtual network device was updated.
+ */
+ VIRTUAL_DEVICE_UPDATED,
+ /**
+ * Signifies that a virtual network device was removed.
+ */
+ VIRTUAL_DEVICE_REMOVED,
+ /**
+ * Signifies that a new virtual network port was added.
+ */
+ VIRTUAL_PORT_ADDED,
+ /**
+ * Signifies that a virtual network port was updated.
+ */
+ VIRTUAL_PORT_UPDATED,
+ /**
+ * Signifies that a virtual network port was removed.
+ */
+ VIRTUAL_PORT_REMOVED
+ }
+
+ private final VirtualDevice virtualDevice;
+ private final VirtualPort virtualPort;
+
+ /**
+ * Creates an event of a given type and for the specified subject.
+ *
+ * @param type event type
+ * @param subject event subject
+ */
+ public VirtualNetworkEvent(Type type, NetworkId subject) {
+ this(type, subject, null, null);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject and the
+ * virtual device.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param virtualDevice virtual device
+ */
+ public VirtualNetworkEvent(Type type, NetworkId subject, VirtualDevice virtualDevice) {
+ this(type, subject, virtualDevice, null);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject, virtual device and
+ * virtual port.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param virtualDevice virtual device
+ * @param virtualPort virtual port
+ */
+ public VirtualNetworkEvent(Type type, NetworkId subject, VirtualDevice virtualDevice,
+ VirtualPort virtualPort) {
+ super(type, subject);
+ this.virtualDevice = virtualDevice;
+ this.virtualPort = virtualPort;
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject and time.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param time occurrence time
+ */
+ public VirtualNetworkEvent(Type type, NetworkId subject, long time) {
+ this(type, subject, null, null, time);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject, virtual device and time.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param virtualDevice virtual device
+ * @param time occurrence time
+ */
+ public VirtualNetworkEvent(Type type, NetworkId subject, VirtualDevice virtualDevice,
+ long time) {
+ this(type, subject, virtualDevice, null, time);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject, virtual port and time.
+ *
+ * @param type device event type
+ * @param subject event subject
+ * @param virtualPort virtual port
+ * @param time occurrence time
+ */
+ public VirtualNetworkEvent(Type type, NetworkId subject, VirtualPort virtualPort,
+ long time) {
+ this(type, subject, null, virtualPort, time);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject, virtual device,
+ * virtual port and time.
+ *
+ * @param type device event type
+ * @param subject event subject
+ * @param virtualDevice virtual device
+ * @param virtualPort virtual port
+ * @param time occurrence time
+ */
+ private VirtualNetworkEvent(Type type, NetworkId subject, VirtualDevice virtualDevice,
+ VirtualPort virtualPort, long time) {
+ super(type, subject, time);
+ this.virtualDevice = virtualDevice;
+ this.virtualPort = virtualPort;
+ }
+
+ /**
+ * Returns virtual device affected by event - may be null (for events relating to
+ * tenants and virtual networks).
+ *
+ * @return virtual device
+ */
+ public VirtualDevice virtualDevice() {
+ return virtualDevice;
+ }
+
+ /**
+ * Returns virtual port affected by event - may be null (for events relating to
+ * tenants, virtual networks and virtual devices).
+ *
+ * @return virtual port
+ */
+ public VirtualPort virtualPort() {
+ return virtualPort;
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowObjectiveStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowObjectiveStore.java
new file mode 100644
index 0000000..c118958
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowObjectiveStore.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.net.behaviour.NextGroup;
+import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
+import org.onosproject.net.flowobjective.ObjectiveEvent;
+
+import java.util.Map;
+
+/**
+ * The flow objective store for virtual networks.
+ */
+public interface VirtualNetworkFlowObjectiveStore
+ extends VirtualStore<ObjectiveEvent, FlowObjectiveStoreDelegate> {
+
+ /**
+ * Adds a NextGroup to the store, by mapping it to the nextId as key,
+ * and replacing any previous mapping.
+ *
+ * @param networkId a virtual network identifier
+ * @param nextId an integer
+ * @param group a next group opaque object
+ */
+ void putNextGroup(NetworkId networkId, Integer nextId, NextGroup group);
+
+ /**
+ * Fetch a next group from the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param nextId an integer used as key
+ * @return a next group, or null if group was not found
+ */
+ NextGroup getNextGroup(NetworkId networkId, Integer nextId);
+
+ /**
+ * Remove a next group mapping from the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param nextId the key to remove from the store.
+ * @return the next group which mapped to the nextId and is now removed, or
+ * null if no group mapping existed in the store
+ */
+ NextGroup removeNextGroup(NetworkId networkId, Integer nextId);
+
+ /**
+ * Fetch all groups from the store and their mapping to nextIds.
+ *
+ * @param networkId a virtual network identifier
+ * @return a map that represents the current snapshot of Next-ids to NextGroups
+ */
+ Map<Integer, NextGroup> getAllGroups(NetworkId networkId);
+
+ /**
+ * Allocates a next objective id. This id is globally unique.
+ *
+ * @param networkId a virtual network identifier
+ * @return an integer
+ */
+ int allocateNextId(NetworkId networkId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowRuleStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowRuleStore.java
new file mode 100644
index 0000000..6b532c3
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowRuleStore.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.net.DeviceId;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.FlowRuleEvent;
+import org.onosproject.net.flow.FlowRuleStoreDelegate;
+import org.onosproject.net.flow.TableStatisticsEntry;
+
+import java.util.List;
+
+/**
+ * Manages inventory of flow rules for virtual networks;
+ * not intended for direct use.
+ */
+public interface VirtualNetworkFlowRuleStore
+ extends VirtualStore<FlowRuleBatchEvent, FlowRuleStoreDelegate> {
+ /**
+ * Returns the number of flow rule in the store.
+ *
+ * @param networkId virtual network identifier
+ * @return number of flow rules
+ */
+ int getFlowRuleCount(NetworkId networkId);
+
+ /**
+ * Returns the stored flow.
+ *
+ * @param networkId virtual network identifier
+ * @param rule the rule to look for
+ * @return a flow rule
+ */
+ FlowEntry getFlowEntry(NetworkId networkId, FlowRule rule);
+
+ /**
+ * Returns the flow entries associated with a device.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId the device ID
+ * @return the flow entries
+ */
+ Iterable<FlowEntry> getFlowEntries(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Stores a batch of flow rules.
+ *
+ * @param networkId virtual network identifier
+ * @param batchOperation batch of flow rules.
+ * A batch can contain flow rules for a single device only.
+ *
+ */
+ void storeBatch(NetworkId networkId, FlowRuleBatchOperation batchOperation);
+
+ /**
+ * Invoked on the completion of a storeBatch operation.
+ *
+ * @param networkId virtual network identifier
+ * @param event flow rule batch event
+ */
+ void batchOperationComplete(NetworkId networkId, FlowRuleBatchEvent event);
+
+ /**
+ * Marks a flow rule for deletion. Actual deletion will occur
+ * when the provider indicates that the flow has been removed.
+ *
+ * @param networkId virtual network identifier
+ * @param rule the flow rule to delete
+ */
+ void deleteFlowRule(NetworkId networkId, FlowRule rule);
+
+ /**
+ * Stores a new flow rule, or updates an existing entry.
+ *
+ * @param networkId virtual network identifier
+ * @param rule the flow rule to add or update
+ * @return flow_added event, or null if just an update
+ */
+ FlowRuleEvent addOrUpdateFlowRule(NetworkId networkId, FlowEntry rule);
+
+ /**
+ * Removes an existing flow entry.
+ *
+ * @param rule the flow entry to remove
+ * @param networkId virtual network identifier
+ * @return flow_removed event, or null if nothing removed
+ */
+ FlowRuleEvent removeFlowRule(NetworkId networkId, FlowEntry rule);
+
+ /**
+ * Marks a flow rule as PENDING_ADD during retry.
+ *
+ * Emits flow_update event if the state is changed
+ *
+ * @param networkId virtual network identifier
+ * @param rule the flow rule that is retrying
+ * @return flow_updated event, or null if nothing updated
+ */
+ FlowRuleEvent pendingFlowRule(NetworkId networkId, FlowEntry rule);
+
+ /**
+ * Removes all flow entries of given device from store.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId device id
+ */
+ default void purgeFlowRule(NetworkId networkId, DeviceId deviceId) {}
+
+ /**
+ * Removes all flow entries from store.
+ *
+ * @param networkId virtual network identifier
+ */
+ void purgeFlowRules(NetworkId networkId);
+
+ /**
+ * Updates the flow table statistics of the specified device using
+ * the given statistics.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId device identifier
+ * @param tableStats list of table statistics
+ * @return ready to send event describing what occurred;
+ */
+ FlowRuleEvent updateTableStatistics(NetworkId networkId, DeviceId deviceId,
+ List<TableStatisticsEntry> tableStats);
+
+ /**
+ * Returns the flow table statistics associated with a device.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId the device ID
+ * @return the flow table statistics
+ */
+ Iterable<TableStatisticsEntry> getTableStatistics(NetworkId networkId, DeviceId deviceId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkGroupStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkGroupStore.java
new file mode 100644
index 0000000..d080524
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkGroupStore.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.core.GroupId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupEvent;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupOperation;
+import org.onosproject.net.group.GroupStoreDelegate;
+
+import java.util.Collection;
+
+/**
+ * Manages inventory of groups per virtual network and virtual device;
+ * not intended for direct use.
+ */
+public interface VirtualNetworkGroupStore
+ extends VirtualStore<GroupEvent, GroupStoreDelegate> {
+
+ enum UpdateType {
+ /**
+ * Modify existing group entry by adding provided information.
+ */
+ ADD,
+ /**
+ * Modify existing group by removing provided information from it.
+ */
+ REMOVE,
+ /**
+ * Modify existing group entry by setting the provided information,
+ * overwriting the previous group entry entirely.
+ */
+ SET
+ }
+
+ /**
+ * Returns the number of groups for the specified virtual device in the store.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @return number of groups for the specified device
+ */
+ int getGroupCount(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns the groups associated with a virtual device.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @return the group entries
+ */
+ Iterable<Group> getGroups(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns the stored group entry in a virtual network.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @param appCookie the group key
+ * @return a group associated with the key
+ */
+ Group getGroup(NetworkId networkId, DeviceId deviceId, GroupKey appCookie);
+
+ /**
+ * Returns the stored group entry for an id.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @param groupId the group identifier
+ * @return a group associated with the key
+ */
+ Group getGroup(NetworkId networkId, DeviceId deviceId, GroupId groupId);
+
+ /**
+ * Stores a new group entry using the information from group description
+ * for a virtual network.
+ *
+ * @param networkId the virtual network ID
+ * @param groupDesc group description to be used to store group entry
+ */
+ void storeGroupDescription(NetworkId networkId, GroupDescription groupDesc);
+
+ /**
+ * Updates the existing group entry with the information
+ * from group description.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @param oldAppCookie the current group key
+ * @param type update type
+ * @param newBuckets group buckets for updates
+ * @param newAppCookie optional new group key
+ */
+ void updateGroupDescription(NetworkId networkId,
+ DeviceId deviceId,
+ GroupKey oldAppCookie,
+ UpdateType type,
+ GroupBuckets newBuckets,
+ GroupKey newAppCookie);
+
+ /**
+ * Triggers deleting the existing group entry.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @param appCookie the group key
+ */
+ void deleteGroupDescription(NetworkId networkId,
+ DeviceId deviceId,
+ GroupKey appCookie);
+
+ /**
+ * Stores a new group entry, or updates an existing entry.
+ *
+ * @param networkId the virtual network ID
+ * @param group group entry
+ */
+ void addOrUpdateGroupEntry(NetworkId networkId, Group group);
+
+ /**
+ * Removes the group entry from store.
+ *
+ * @param networkId the virtual network ID
+ * @param group group entry
+ */
+ void removeGroupEntry(NetworkId networkId, Group group);
+
+ /**
+ * Removes all group entries of given device from store.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId device id
+ */
+ void purgeGroupEntry(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Removes all group entries from store.
+ *
+ * @param networkId the virtual network ID
+ */
+ default void purgeGroupEntries(NetworkId networkId) {}
+
+ /**
+ * A group entry that is present in switch but not in the store.
+ *
+ * @param networkId the virtual network ID
+ * @param group group entry
+ */
+ void addOrUpdateExtraneousGroupEntry(NetworkId networkId, Group group);
+
+ /**
+ * Remove the group entry from extraneous database.
+ *
+ * @param networkId the virtual network ID
+ * @param group group entry
+ */
+ void removeExtraneousGroupEntry(NetworkId networkId, Group group);
+
+ /**
+ * Returns the extraneous groups associated with a device.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ *
+ * @return the extraneous group entries
+ */
+ Iterable<Group> getExtraneousGroups(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Indicates the first group audit is completed.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @param completed initial audit status
+ */
+ void deviceInitialAuditCompleted(NetworkId networkId, DeviceId deviceId, boolean completed);
+
+ /**
+ * Retrieves the initial group audit status for a device.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ *
+ * @return initial group audit status
+ */
+ boolean deviceInitialAuditStatus(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Indicates the group operations failed.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @param operation the group operation failed
+ */
+ void groupOperationFailed(NetworkId networkId, DeviceId deviceId, GroupOperation operation);
+
+ /**
+ * Submits the group metrics to store for a given device ID.
+ *
+ * @param networkId the virtual network ID
+ * @param deviceId the device ID
+ * @param groupEntries the group entries as received from southbound
+ */
+ void pushGroupMetrics(NetworkId networkId, DeviceId deviceId, Collection<Group> groupEntries);
+
+ /**
+ * Indicates failover within a failover group.
+ *
+ * @param networkId the virtual network ID
+ * @param failoverGroups groups to notify
+ */
+ void notifyOfFailovers(NetworkId networkId, Collection<Group> failoverGroups);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntent.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntent.java
new file mode 100644
index 0000000..817db21
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntent.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.ResourceGroup;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.ConnectivityIntent;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Key;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of VirtualNetworkIntent connectivity.
+ */
+@Beta
+public final class VirtualNetworkIntent extends ConnectivityIntent {
+
+ private final NetworkId networkId;
+ private final ConnectPoint ingressPoint;
+ private final ConnectPoint egressPoint;
+
+ private static final String NETWORK_ID_NULL = "Network ID cannot be null";
+
+ /**
+ * Returns a new point to point intent builder. The application id,
+ * ingress point and egress point are required fields. If they are
+ * not set by calls to the appropriate methods, an exception will
+ * be thrown.
+ *
+ * @return point to point builder
+ */
+ public static VirtualNetworkIntent.Builder builder() {
+ return new VirtualNetworkIntent.Builder();
+ }
+
+ /**
+ * Builder of a point to point intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ NetworkId networkId;
+ ConnectPoint ingressPoint;
+ ConnectPoint egressPoint;
+
+ /**
+ * Builder constructor.
+ */
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ @Override
+ public Builder resourceGroup(ResourceGroup resourceGroup) {
+ return (Builder) super.resourceGroup(resourceGroup);
+ }
+
+ /**
+ * Sets the virtual network of the virtual network intent.
+ *
+ * @param networkId virtual network identifier
+ * @return this builder
+ */
+ public VirtualNetworkIntent.Builder networkId(NetworkId networkId) {
+ this.networkId = networkId;
+ return this;
+ }
+
+ /**
+ * Sets the ingress point of the virtual network intent that will be built.
+ *
+ * @param ingressPoint ingress connect point
+ * @return this builder
+ */
+ public VirtualNetworkIntent.Builder ingressPoint(ConnectPoint ingressPoint) {
+ this.ingressPoint = ingressPoint;
+ return this;
+ }
+
+ /**
+ * Sets the egress point of the virtual network intent that will be built.
+ *
+ * @param egressPoint egress connect point
+ * @return this builder
+ */
+ public VirtualNetworkIntent.Builder egressPoint(ConnectPoint egressPoint) {
+ this.egressPoint = egressPoint;
+ return this;
+ }
+
+ /**
+ * Builds a virtual network intent from the accumulated parameters.
+ *
+ * @return virtual network intent
+ */
+ public VirtualNetworkIntent build() {
+
+ return new VirtualNetworkIntent(
+ networkId,
+ appId,
+ key,
+ selector,
+ treatment,
+ ingressPoint,
+ egressPoint,
+ constraints,
+ priority,
+ resourceGroup
+ );
+ }
+ }
+
+
+ /**
+ * Creates a new point-to-point intent with the supplied ingress/egress
+ * ports and constraints.
+ *
+ * @param networkId virtual network identifier
+ * @param appId application identifier
+ * @param key key of the intent
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param ingressPoint ingress port
+ * @param egressPoint egress port
+ * @param constraints optional list of constraints
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if {@code ingressPoint} or
+ * {@code egressPoints} or {@code appId} is null.
+ */
+ private VirtualNetworkIntent(NetworkId networkId,
+ ApplicationId appId,
+ Key key,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ ConnectPoint ingressPoint,
+ ConnectPoint egressPoint,
+ List<Constraint> constraints,
+ int priority,
+ ResourceGroup resourceGroup) {
+ super(appId, key, Collections.emptyList(), selector, treatment, constraints,
+ priority, resourceGroup);
+
+ checkNotNull(networkId, NETWORK_ID_NULL);
+ checkArgument(!ingressPoint.equals(egressPoint),
+ "ingress and egress should be different (ingress: %s, egress: %s)", ingressPoint, egressPoint);
+
+ this.networkId = networkId;
+ this.ingressPoint = checkNotNull(ingressPoint);
+ this.egressPoint = checkNotNull(egressPoint);
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected VirtualNetworkIntent() {
+ super();
+ this.networkId = null;
+ this.ingressPoint = null;
+ this.egressPoint = null;
+ }
+
+ /**
+ * Returns the virtual network identifier.
+ *
+ * @return network identifier
+ */
+ public NetworkId networkId() {
+ return networkId;
+ }
+
+ /**
+ * Returns the port on which the ingress traffic should be connected to
+ * the egress.
+ *
+ * @return ingress port
+ */
+ public ConnectPoint ingressPoint() {
+ return ingressPoint;
+ }
+
+ /**
+ * Returns the port on which the traffic should egress.
+ *
+ * @return egress port
+ */
+ public ConnectPoint egressPoint() {
+ return egressPoint;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("networkId", networkId)
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("ingress", ingressPoint)
+ .add("egress", egressPoint)
+ .add("constraints", constraints())
+ .add("resourceGroup", resourceGroup())
+ .toString();
+ }
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntentStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntentStore.java
new file mode 100644
index 0000000..f8b42c1
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntentStore.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.IntentStoreDelegate;
+import org.onosproject.net.intent.Key;
+
+import java.util.List;
+
+public interface VirtualNetworkIntentStore
+ extends VirtualStore<IntentEvent, IntentStoreDelegate> {
+
+ /**
+ * Returns the number of intents in the store.
+ *
+ * @param networkId the virtual network identifier
+ * @return the number of intents in the store
+ */
+ long getIntentCount(NetworkId networkId);
+
+ /**
+ * Returns an iterable of all intents in the store.
+ *
+ * @param networkId the virtual network identifier
+ * @return iterable of all intents
+ */
+ Iterable<Intent> getIntents(NetworkId networkId);
+
+ /**
+ * Returns an iterable of all intent data objects in the store.
+ *
+ * @param networkId the virtual network identifier
+ * @param localOnly should only intents for which this instance is master
+ * be returned
+ * @param olderThan specified duration in milliseconds (0 for "now")
+ * @return iterable of all intent data objects
+ */
+ Iterable<IntentData> getIntentData(NetworkId networkId, boolean localOnly,
+ long olderThan);
+
+ /**
+ * Returns the state of the specified intent.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey intent identification
+ * @return current intent state
+ */
+ IntentState getIntentState(NetworkId networkId, Key intentKey);
+
+ /**
+ * Returns the list of the installable events associated with the specified
+ * original intent.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey original intent identifier
+ * @return compiled installable intents, or null if no installables exist
+ */
+ List<Intent> getInstallableIntents(NetworkId networkId, Key intentKey);
+
+ /**
+ * Writes an IntentData object to the store.
+ *
+ * @param networkId the virtual network identifier
+ * @param newData new intent data to write
+ */
+ void write(NetworkId networkId, IntentData newData);
+
+ /**
+ * Writes a batch of IntentData objects to the store. A batch has no
+ * semantics, this is simply a convenience API.
+ *
+ * @param networkId the virtual network identifier
+ * @param updates collection of intent data objects to write
+ */
+ void batchWrite(NetworkId networkId, Iterable<IntentData> updates);
+
+ /**
+ * Returns the intent with the specified identifier.
+ *
+ * @param networkId the virtual network identifier
+ * @param key key
+ * @return intent or null if not found
+ */
+ Intent getIntent(NetworkId networkId, Key key);
+
+ /**
+ * Returns the intent data object associated with the specified key.
+ *
+ * @param networkId the virtual network identifier
+ * @param key key to look up
+ * @return intent data object
+ */
+ IntentData getIntentData(NetworkId networkId, Key key);
+
+ /**
+ * Adds a new operation, which should be persisted and delegated.
+ *
+ * @param networkId the virtual network identifier
+ * @param intent operation
+ */
+ void addPending(NetworkId networkId, IntentData intent);
+
+ /**
+ * Checks to see whether the calling instance is the master for processing
+ * this intent, or more specifically, the key contained in this intent.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey intentKey to check
+ * @return true if master; false, otherwise
+ */
+ //TODO better name
+ boolean isMaster(NetworkId networkId, Key intentKey);
+
+ /**
+ * Returns the intent requests pending processing.
+ *
+ * @param networkId the virtual network identifier
+ * @return pending intents
+ */
+ Iterable<Intent> getPending(NetworkId networkId);
+
+ /**
+ * Returns the intent data objects that are pending processing.
+ *
+ * @param networkId the virtual network identifier
+ * @return pending intent data objects
+ */
+ Iterable<IntentData> getPendingData(NetworkId networkId);
+
+ /**
+ * Returns the intent data object that are pending processing for a specfied
+ * key.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey key to look up
+ * @return pending intent data object
+ */
+ IntentData getPendingData(NetworkId networkId, Key intentKey);
+
+ /**
+ * Returns the intent data objects that are pending processing for longer
+ * than the specified duration.
+ *
+ * @param networkId the virtual network identifier
+ * @param localOnly should only intents for which this instance is master
+ * be returned
+ * @param olderThan specified duration in milliseconds (0 for "now")
+ * @return pending intent data objects
+ */
+ Iterable<IntentData> getPendingData(NetworkId networkId, boolean localOnly, long olderThan);
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkListener.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkListener.java
new file mode 100644
index 0000000..cc6d663
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkMastershipStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkMastershipStore.java
new file mode 100644
index 0000000..31fdfcd
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkMastershipStore.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.cluster.NodeId;
+import org.onosproject.cluster.RoleInfo;
+import org.onosproject.mastership.MastershipEvent;
+import org.onosproject.mastership.MastershipInfo;
+import org.onosproject.mastership.MastershipStoreDelegate;
+import org.onosproject.mastership.MastershipTerm;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Manages inventory of mastership roles for devices, across controller
+ * instances for virtual networks; not intended for direct use.
+ */
+public interface VirtualNetworkMastershipStore
+ extends VirtualStore<MastershipEvent, MastershipStoreDelegate> {
+
+ // three things to map: NodeId, DeviceId, MastershipRole
+
+ /**
+ * Requests role of the local node for the specified device.
+ *
+ * @param networkId the virtual network identifier
+ * @param deviceId the device identifier
+ * @return established or newly negotiated mastership role
+ */
+ CompletableFuture<MastershipRole> requestRole(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns the role of a device for a specific controller instance.
+ *
+ * @param networkId virtual network identifier
+ * @param nodeId the instance identifier
+ * @param deviceId the device identifiers
+ * @return the role
+ */
+ MastershipRole getRole(NetworkId networkId, NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Returns the master for a device.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId the device identifier
+ * @return the instance identifier of the master
+ */
+ NodeId getMaster(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns the master and backup nodes for a device.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId the device identifier
+ * @return a RoleInfo containing controller IDs
+ */
+ RoleInfo getNodes(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns the mastership info for a device.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId the device identifier
+ * @return the mastership info
+ */
+ MastershipInfo getMastership(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns the devices that a controller instance is master of.
+ *
+ * @param networkId virtual network identifier
+ * @param nodeId the instance identifier
+ * @return a set of device identifiers
+ */
+ Set<DeviceId> getDevices(NetworkId networkId, NodeId nodeId);
+
+
+ /**
+ * Sets a device's role for a specified controller instance.
+ *
+ * @param networkId virtual network identifier
+ * @param nodeId controller instance identifier
+ * @param deviceId device identifier
+ * @return a mastership event
+ */
+ CompletableFuture<MastershipEvent> setMaster(NetworkId networkId,
+ NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Returns the current master and number of past mastership hand-offs
+ * (terms) for a device.
+ *
+ * @param networkId virtual network identifier
+ * @param deviceId the device identifier
+ * @return the current master's ID and the term value for device, or null
+ */
+ MastershipTerm getTermFor(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Sets a controller instance's mastership role to STANDBY for a device.
+ * If the role is MASTER, another controller instance will be selected
+ * as a candidate master.
+ *
+ * @param networkId virtual network identifier
+ * @param nodeId the controller instance identifier
+ * @param deviceId device to revoke mastership role for
+ * @return a mastership event
+ */
+ CompletableFuture<MastershipEvent> setStandby(NetworkId networkId,
+ NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Allows a controller instance to give up its current role for a device.
+ * If the role is MASTER, another controller instance will be selected
+ * as a candidate master.
+ *
+ * @param networkId virtual network identifier
+ * @param nodeId the controller instance identifier
+ * @param deviceId device to revoke mastership role for
+ * @return a mastership event
+ */
+ CompletableFuture<MastershipEvent> relinquishRole(NetworkId networkId,
+ NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Removes all the roles for the specified controller instance.
+ * If the role was MASTER, another controller instance will be selected
+ * as a candidate master.
+ *
+ * @param networkId virtual network identifier
+ * @param nodeId the controller instance identifier
+ */
+ void relinquishAllRole(NetworkId networkId, NodeId nodeId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkMeterStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkMeterStore.java
new file mode 100644
index 0000000..954f66b
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkMeterStore.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.net.DeviceId;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterEvent;
+import org.onosproject.net.meter.MeterFailReason;
+import org.onosproject.net.meter.MeterFeatures;
+import org.onosproject.net.meter.MeterFeaturesKey;
+import org.onosproject.net.meter.MeterKey;
+import org.onosproject.net.meter.MeterOperation;
+import org.onosproject.net.meter.MeterStoreDelegate;
+import org.onosproject.net.meter.MeterStoreResult;
+
+import java.util.Collection;
+import java.util.concurrent.CompletableFuture;
+
+public interface VirtualNetworkMeterStore
+ extends VirtualStore<MeterEvent, MeterStoreDelegate> {
+
+ /**
+ * Adds a meter to the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param meter a meter
+ * @return a future indicating the result of the store operation
+ */
+ CompletableFuture<MeterStoreResult> storeMeter(NetworkId networkId, Meter meter);
+
+ /**
+ * Deletes a meter from the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param meter a meter
+ * @return a future indicating the result of the store operation
+ */
+ CompletableFuture<MeterStoreResult> deleteMeter(NetworkId networkId, Meter meter);
+
+
+ /**
+ * Adds the meter features to the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param meterfeatures the meter features
+ * @return the result of the store operation
+ */
+ MeterStoreResult storeMeterFeatures(NetworkId networkId, MeterFeatures meterfeatures);
+
+ /**
+ * Deletes the meter features from the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param deviceId the device id
+ * @return a future indicating the result of the store operation
+ */
+ MeterStoreResult deleteMeterFeatures(NetworkId networkId, DeviceId deviceId);
+
+
+ /**
+ * Updates a meter whose meter id is the same as the passed meter.
+ *
+ * @param networkId a virtual network identifier
+ * @param meter a new meter
+ * @return a future indicating the result of the store operation
+ */
+ CompletableFuture<MeterStoreResult> updateMeter(NetworkId networkId, Meter meter);
+
+ /**
+ * Updates a given meter's state with the provided state.
+ *
+ * @param networkId a virtual network identifier
+ * @param meter a meter
+ */
+ void updateMeterState(NetworkId networkId, Meter meter);
+
+ /**
+ * Obtains a meter matching the given meter key.
+ *
+ * @param networkId a virtual network identifier
+ * @param key a meter key
+ * @return a meter
+ */
+ Meter getMeter(NetworkId networkId, MeterKey key);
+
+ /**
+ * Returns all meters stored in the store.
+ *
+ * @param networkId a virtual network identifier
+ * @return a collection of meters
+ */
+ Collection<Meter> getAllMeters(NetworkId networkId);
+
+ /**
+ * Update the store by deleting the failed meter.
+ * Notifies the delegate that the meter failed to allow it
+ * to nofity the app.
+ *
+ * @param networkId a virtual network identifier
+ * @param op a failed meter operation
+ * @param reason a failure reason
+ */
+ void failedMeter(NetworkId networkId, MeterOperation op, MeterFailReason reason);
+
+ /**
+ * Delete this meter immediately.
+ *
+ * @param networkId a virtual network identifier
+ * @param m a meter
+ */
+ void deleteMeterNow(NetworkId networkId, Meter m);
+
+ /**
+ * Retrieve maximum meters available for the device.
+ *
+ * @param networkId a virtual network identifier
+ * @param key the meter features key
+ * @return the maximum number of meters supported by the device
+ */
+ long getMaxMeters(NetworkId networkId, MeterFeaturesKey key);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkPacketStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkPacketStore.java
new file mode 100644
index 0000000..4cf5cb9
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkPacketStore.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketEvent;
+import org.onosproject.net.packet.PacketRequest;
+import org.onosproject.net.packet.PacketStoreDelegate;
+
+import java.util.List;
+
+public interface VirtualNetworkPacketStore
+ extends VirtualStore<PacketEvent, PacketStoreDelegate> {
+ /**
+ * Decides which instance should emit the packet and forwards the packet to
+ * that instance. The relevant PacketManager is notified via the
+ * PacketStoreDelegate that it should emit the packet.
+ *
+ * @param networkId a virtual network identifier
+ * @param packet the packet to emit
+ */
+ void emit(NetworkId networkId, OutboundPacket packet);
+
+ /**
+ * Requests intercept of packets that match the given selector.
+ *
+ * @param networkId a virtual network identifier
+ * @param request a packet request
+ */
+ void requestPackets(NetworkId networkId, PacketRequest request);
+
+ /**
+ * Cancels intercept of packets that match the given selector.
+ *
+ * @param networkId a virtual network identifier
+ * @param request a packet request
+ */
+ void cancelPackets(NetworkId networkId, PacketRequest request);
+
+ /**
+ * Obtains all existing requests in the system.
+ *
+ * @param networkId a virtual network identifier
+ * @return list of packet requests in order of priority
+ */
+ List<PacketRequest> existingRequests(NetworkId networkId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkService.java
new file mode 100644
index 0000000..d0e4fd1
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkService.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.TenantId;
+
+import java.util.Set;
+
+/**
+ * Service for querying virtual network inventory.
+ */
+@Beta
+public interface VirtualNetworkService
+ extends ListenerService<VirtualNetworkEvent, VirtualNetworkListener> {
+
+ /**
+ * The topic used for obtaining globally unique ids.
+ */
+ String VIRTUAL_NETWORK_TOPIC = "virtual-network-ids";
+
+ /**
+ * Returns a collection of all virtual networks created on behalf of the
+ * specified tenant.
+ *
+ * @param tenantId tenant identifier
+ * @return collection of networks
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId);
+
+ /**
+ * Returns the virtual network matching the network identifier.
+ *
+ * @param networkId virtual network identifier
+ * @return virtual network instance
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ VirtualNetwork getVirtualNetwork(NetworkId networkId);
+
+ /**
+ * Returns {@code tenantId} for specified virtual network id.
+ *
+ * @param networkId virtual network identifier
+ * @return tenantId tenant identifier
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ TenantId getTenantId(NetworkId networkId);
+
+ /**
+ * Returns a collection of all virtual devices in the specified network.
+ *
+ * @param networkId network identifier
+ * @return collection of devices
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ Set<VirtualDevice> getVirtualDevices(NetworkId networkId);
+
+ /**
+ * Returns a collection of all virtual hosts in the specified network.
+ *
+ * @param networkId network identifier
+ * @return collection of hosts
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ Set<VirtualHost> getVirtualHosts(NetworkId networkId);
+
+ /**
+ * Returns collection of all virtual links in the specified network.
+ *
+ * @param networkId network identifier
+ * @return collection of links
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ Set<VirtualLink> getVirtualLinks(NetworkId networkId);
+
+ /**
+ * Returns list of all virtual ports of the specified device. If the
+ * device identifier is null then all of the virtual ports in the specified
+ * network will be returned.
+ *
+ * @param networkId network identifier
+ * @param deviceId device identifier
+ * @return list of ports
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ */
+ Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns list of physical device identifier mapping with the virtual
+ * device in the specified network. The physical devices are specified by
+ * port mapping mechanism.
+ *
+ * @param networkId network identifier
+ * @param deviceId the virtual device identifier
+ * @return collection of the specified device's identifier
+ */
+ Set<DeviceId> getPhysicalDevices(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns implementation of the specified service class for operating
+ * in the context of the given network.
+ * <p>
+ * The following services will be available:
+ * <ul>
+ * <li>{@link org.onosproject.net.device.DeviceService}</li>
+ * <li>{@link org.onosproject.net.link.LinkService}</li>
+ * <li>{@link org.onosproject.net.host.HostService}</li>
+ * <li>{@link org.onosproject.net.topology.TopologyService}</li>
+ * <li>{@link org.onosproject.net.topology.PathService}</li>
+ * <li>{@link org.onosproject.net.packet.PacketService}</li>
+ * <li>{@link org.onosproject.net.flow.FlowRuleService}</li>
+ * <li>{@link org.onosproject.net.flowobjective.FlowObjectiveService}</li>
+ * <li>{@link org.onosproject.net.intent.IntentService}</li>
+ * <li>{@link org.onosproject.mastership.MastershipService}</li>
+ * <li>{@link org.onosproject.mastership.MastershipAdminService}</li>
+ * <li>{@link org.onosproject.mastership.MastershipTermService}</li>
+ * </ul>
+ *
+ * @param networkId network identifier
+ * @param serviceClass service class
+ * @param <T> type of service
+ * @return implementation class
+ * @throws org.onlab.util.ItemNotFoundException if no such network found
+ * @throws org.onlab.osgi.ServiceNotFoundException if no implementation found
+ */
+ <T> T get(NetworkId networkId, Class<T> serviceClass);
+
+ /**
+ * Returns service directory.
+ *
+ * @return a service directory
+ */
+ ServiceDirectory getServiceDirectory();
+
+ /**
+ * Returns the application identifier for a virtual network.
+ *
+ * @param networkId network identifier
+ * @return an representative application identifier for a virtual network
+ */
+ ApplicationId getVirtualNetworkApplicationId(NetworkId networkId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
new file mode 100644
index 0000000..de74333
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.TenantId;
+import org.onosproject.net.intent.Intent;
+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);
+
+ /**
+ * Removes 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 host to the store.
+ *
+ * @param networkId network identifier
+ * @param hostId host identifier
+ * @param mac mac address
+ * @param vlan vlan identifier
+ * @param location host location
+ * @param ips set of ip addresses
+ * @return the virtual host
+ */
+ VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
+ VlanId vlan, HostLocation location, Set<IpAddress> ips);
+
+ /**
+ * Removes the specified virtual host from the store.
+ *
+ * @param networkId network identifier
+ * @param hostId host identifier
+ */
+ void removeHost(NetworkId networkId, HostId hostId);
+
+ /**
+ * 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 state link state
+ * @param realizedBy underlying tunnel identifier using which this link is realized
+ * @return the virtual link
+ */
+ VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, Link.State state, TunnelId realizedBy);
+
+ /**
+ * Updates the tunnelId in the virtual link.
+ *
+ * @param virtualLink virtual link
+ * @param tunnelId tunnel identifier
+ * @param state link state
+ */
+ void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state);
+
+ /**
+ * Removes the specified link from the store.
+ *
+ * @param networkId network identifier
+ * @param src source connection point
+ * @param dst destination connection point
+ * @return the virtual link
+ */
+ VirtualLink 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, ConnectPoint realizedBy);
+
+ /**
+ * Binds an existing 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
+ */
+ void bindPort(NetworkId networkId, DeviceId deviceId,
+ PortNumber portNumber, ConnectPoint realizedBy);
+
+ /**
+ * Updates port state of an existing virtual port.
+ *
+ * @param networkId network identifier
+ * @param deviceId device identifier
+ * @param portNumber port number
+ * @param isEnabled indicator whether the port is up and active
+ */
+ void updatePortState(NetworkId networkId, DeviceId deviceId,
+ PortNumber portNumber, boolean isEnabled);
+
+ /**
+ * 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 virtual network for the given network identifier.
+ *
+ * @param networkId network identifier
+ * @return the virtual network
+ */
+ VirtualNetwork getNetwork(NetworkId networkId);
+
+ /**
+ * 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 hosts in the specified virtual network.
+ *
+ * @param networkId network identifier
+ * @return set of virtual hosts
+ */
+ Set<VirtualHost> getHosts(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 virtual link matching the network identifier, source connect point,
+ * and destination connect point.
+ *
+ * @param networkId network identifier
+ * @param src source connect point
+ * @param dst destination connect point
+ * @return virtual link
+ */
+ VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
+
+ /**
+ * 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);
+
+ /**
+ * Adds the intent to tunnel identifier mapping to the store.
+ *
+ * @param intent intent
+ * @param tunnelId tunnel identifier
+ * @deprecated in Kingfisher Release (1.10)
+ */
+ @Deprecated
+ void addTunnelId(Intent intent, TunnelId tunnelId);
+
+ /**
+ * Return the set of tunnel identifiers store against the intent.
+ *
+ * @param intent intent
+ * @return set of tunnel identifiers
+ * @deprecated in Kingfisher Release (1.10)
+ */
+ @Deprecated
+ Set<TunnelId> getTunnelIds(Intent intent);
+
+ /**
+ * Removes the intent to tunnel identifier mapping from the store.
+ *
+ * @param intent intent
+ * @param tunnelId tunnel identifier
+ * @deprecated in Kingfisher Release (1.10)
+ */
+ @Deprecated
+ void removeTunnelId(Intent intent, TunnelId tunnelId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStoreDelegate.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStoreDelegate.java
new file mode 100644
index 0000000..202a0be
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPacketContext.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPacketContext.java
new file mode 100644
index 0000000..42b548a
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPacketContext.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.packet.PacketContext;
+
+/**
+ * Represents context for processing an inbound packet for a virtual network,
+ * and (optionally) emitting a corresponding outbound packet.
+ */
+public interface VirtualPacketContext extends PacketContext {
+ /**
+ * Returns the network identifier.
+ *
+ * @return network id
+ */
+ NetworkId networkId();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPort.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPort.java
new file mode 100644
index 0000000..a393e8e
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPort.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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 com.google.common.annotations.Beta;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Port;
+
+/**
+ * Representation of a virtual port.
+ */
+@Beta
+public interface VirtualPort extends VirtualElement, Port {
+
+ /**
+ * Returns the underlying port using which this port is realized.
+ *
+ * @return underlying port which realizes this virtual port
+ */
+ ConnectPoint realizedBy();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPortDescription.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPortDescription.java
new file mode 100644
index 0000000..0785641
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPortDescription.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.net.device.PortDescription;
+
+/**
+ * Information about a virtual port.
+ */
+public interface VirtualPortDescription extends PortDescription {
+
+ // TODO: Add something about a requirement of virtual port.
+
+ /**
+ * Representation of the virtual port.
+ */
+ enum State {
+ /**
+ * Signifies that a virtual port is currently start.
+ */
+ START,
+
+ /**
+ * Signifies that a virtual port is currently stop.
+ */
+ STOP,
+
+ /**
+ * Signifies that a virtual port is pause for a moment.
+ */
+ PAUSE
+ }
+
+ /**
+ * Starts the virtual port.
+ */
+ void start();
+
+ /**
+ * Stops the virtual port.
+ */
+ void stop();
+
+ /**
+ * Pauses the virtual port for stopping a network or device.
+ * e.g. snapshot.
+ */
+ void pause();
+
+ /**
+ * Returns the virtual port state.
+ *
+ * @return state of virtual port
+ */
+ State state();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualStore.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualStore.java
new file mode 100644
index 0000000..8a25874
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualStore.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.Event;
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Abstraction of a entity capable of storing and/or distributing information
+ * for virtual network across a cluster.
+ */
+public interface VirtualStore<E extends Event, D extends StoreDelegate<E>> {
+ /**
+ * Sets the delegate on the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param delegate new store delegate
+ * @throws java.lang.IllegalStateException if a delegate is already
+ * currently set on the store and is a different one that
+ */
+ void setDelegate(NetworkId networkId, D delegate);
+
+ /**
+ * Withdraws the delegate from the store.
+ *
+ * @param networkId a virtual network identifier
+ * @param delegate store delegate to withdraw
+ * @throws java.lang.IllegalArgumentException if the delegate is not
+ * currently set on the store
+ */
+ void unsetDelegate(NetworkId networkId, D delegate);
+
+ /**
+ * Indicates whether the store has a delegate.
+ *
+ * @param networkId a virtual network identifier
+ * @return true if delegate is set
+ */
+ boolean hasDelegate(NetworkId networkId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VnetService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VnetService.java
new file mode 100644
index 0000000..1889ad4
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/VnetService.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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;
+
+/**
+ * Virtual network service interface.
+ */
+public interface VnetService {
+ NetworkId networkId();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualDeviceCodec.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualDeviceCodec.java
new file mode 100644
index 0000000..c0c8cf8
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualDeviceCodec.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * Codec for the VirtualDevice class.
+ */
+public class VirtualDeviceCodec extends JsonCodec<VirtualDevice> {
+
+ // JSON field names
+ private static final String ID = "deviceId";
+ private static final String NETWORK_ID = "networkId";
+
+ private static final String NULL_OBJECT_MSG = "VirtualDevice cannot be null";
+ private static final String MISSING_MEMBER_MSG = " member is required in VirtualDevice";
+
+ @Override
+ public ObjectNode encode(VirtualDevice vDev, CodecContext context) {
+ checkNotNull(vDev, NULL_OBJECT_MSG);
+
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(NETWORK_ID, vDev.networkId().toString())
+ .put(ID, vDev.id().toString());
+
+ return result;
+ }
+
+ @Override
+ public VirtualDevice decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ DeviceId dId = DeviceId.deviceId(extractMember(ID, json));
+ NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
+ return new DefaultVirtualDevice(nId, dId);
+ }
+
+ /**
+ * Extract member from JSON ObjectNode.
+ *
+ * @param key key for which value is needed
+ * @param json JSON ObjectNode
+ * @return member value
+ */
+ private String extractMember(String key, ObjectNode json) {
+ return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualHostCodec.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualHostCodec.java
new file mode 100644
index 0000000..2ddb589
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualHostCodec.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualHost;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.PortNumber;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * Codec for the VirtualHost class.
+ */
+public class VirtualHostCodec extends JsonCodec<VirtualHost> {
+
+ // JSON field names
+ static final String NETWORK_ID = "networkId";
+ static final String HOST_ID = "id";
+ static final String MAC_ADDRESS = "mac";
+ static final String VLAN = "vlan";
+ static final String IP_ADDRESSES = "ipAddresses";
+ static final String HOST_LOCATION = "locations";
+
+ private static final String NULL_OBJECT_MSG = "VirtualHost cannot be null";
+ private static final String MISSING_MEMBER_MSG = " member is required in VirtualHost";
+
+ @Override
+ public ObjectNode encode(VirtualHost vHost, CodecContext context) {
+ checkNotNull(vHost, NULL_OBJECT_MSG);
+
+ final JsonCodec<HostLocation> locationCodec =
+ context.codec(HostLocation.class);
+ final ObjectNode result = context.mapper().createObjectNode()
+ .put(NETWORK_ID, vHost.networkId().toString())
+ .put(HOST_ID, vHost.id().toString())
+ .put(MAC_ADDRESS, vHost.mac().toString())
+ .put(VLAN, vHost.vlan().toString());
+
+ final ArrayNode jsonIpAddresses = result.putArray(IP_ADDRESSES);
+ for (final IpAddress ipAddress : vHost.ipAddresses()) {
+ jsonIpAddresses.add(ipAddress.toString());
+ }
+ result.set(IP_ADDRESSES, jsonIpAddresses);
+
+ final ArrayNode jsonLocations = result.putArray("locations");
+ for (final HostLocation location : vHost.locations()) {
+ jsonLocations.add(locationCodec.encode(location, context));
+ }
+ result.set("locations", jsonLocations);
+
+ return result;
+ }
+
+ @Override
+ public VirtualHost decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
+ MacAddress mac = MacAddress.valueOf(json.get("mac").asText());
+ VlanId vlanId = VlanId.vlanId((short) json.get("vlan").asInt(VlanId.UNTAGGED));
+
+ Set<HostLocation> locations = new HashSet<>();
+ JsonNode locationNodes = json.get("locations");
+ locationNodes.forEach(locationNode -> {
+ PortNumber portNumber = PortNumber.portNumber(locationNode.get("port").asText());
+ DeviceId deviceId = DeviceId.deviceId(locationNode.get("elementId").asText());
+ locations.add(new HostLocation(deviceId, portNumber, 0));
+ });
+
+ HostId id = HostId.hostId(mac, vlanId);
+
+ Iterator<JsonNode> ipStrings = json.get("ipAddresses").elements();
+ Set<IpAddress> ips = new HashSet<>();
+ while (ipStrings.hasNext()) {
+ ips.add(IpAddress.valueOf(ipStrings.next().asText()));
+ }
+
+ return new DefaultVirtualHost(nId, id, mac, vlanId, locations, ips);
+ }
+
+ /**
+ * Extract member from JSON ObjectNode.
+ *
+ * @param key key for which value is needed
+ * @param json JSON ObjectNode
+ * @return member value
+ */
+ private String extractMember(String key, ObjectNode json) {
+ return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualLinkCodec.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualLinkCodec.java
new file mode 100644
index 0000000..641982f
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualLinkCodec.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualLink;
+import org.onosproject.net.Link;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * Codec for the VirtualLink class.
+ */
+public class VirtualLinkCodec extends JsonCodec<VirtualLink> {
+
+ // JSON field names
+ private static final String NETWORK_ID = "networkId";
+
+ private static final String NULL_OBJECT_MSG = "VirtualLink cannot be null";
+ private static final String MISSING_MEMBER_MSG = " member is required in VirtualLink";
+
+ @Override
+ public ObjectNode encode(VirtualLink vLink, CodecContext context) {
+ checkNotNull(vLink, NULL_OBJECT_MSG);
+
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(NETWORK_ID, vLink.networkId().toString());
+ JsonCodec<Link> codec = context.codec(Link.class);
+ ObjectNode linkResult = codec.encode(vLink, context);
+ result.setAll(linkResult);
+ return result;
+ }
+
+ @Override
+ public VirtualLink decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+ JsonCodec<Link> codec = context.codec(Link.class);
+ Link link = codec.decode(json, context);
+ NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
+ return DefaultVirtualLink.builder()
+ .networkId(nId)
+ .src(link.src())
+ .dst(link.dst())
+ .build();
+ }
+
+ /**
+ * Extract member from JSON ObjectNode.
+ *
+ * @param key key for which value is needed
+ * @param json JSON ObjectNode
+ * @return member value
+ */
+ private String extractMember(String key, ObjectNode json) {
+ return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualNetworkCodec.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualNetworkCodec.java
new file mode 100644
index 0000000..32945e4
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualNetworkCodec.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * Codec for the VirtualNetwork class.
+ */
+public class VirtualNetworkCodec extends JsonCodec<VirtualNetwork> {
+
+ // JSON field names
+ private static final String NETWORK_ID = "networkId";
+ private static final String TENANT_ID = "tenantId";
+
+ private static final String NULL_OBJECT_MSG = "VirtualNetwork cannot be null";
+ private static final String MISSING_MEMBER_MSG = " member is required in VirtualNetwork";
+
+ @Override
+ public ObjectNode encode(VirtualNetwork vnet, CodecContext context) {
+ checkNotNull(vnet, NULL_OBJECT_MSG);
+
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(NETWORK_ID, vnet.id().toString())
+ .put(TENANT_ID, vnet.tenantId().toString());
+
+ return result;
+ }
+
+ @Override
+ public VirtualNetwork decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
+ TenantId tId = TenantId.tenantId(extractMember(TENANT_ID, json));
+ return new DefaultVirtualNetwork(nId, tId);
+ }
+
+ private String extractMember(String key, ObjectNode json) {
+ return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualPortCodec.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualPortCodec.java
new file mode 100644
index 0000000..474196e
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/VirtualPortCodec.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.incubator.net.virtual.VirtualPort;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * Codec for the VirtualPort class.
+ */
+public class VirtualPortCodec extends JsonCodec<VirtualPort> {
+
+ // JSON field names
+ private static final String NETWORK_ID = "networkId";
+ private static final String DEVICE_ID = "deviceId";
+ private static final String PORT_NUM = "portNum";
+ private static final String PHYS_DEVICE_ID = "physDeviceId";
+ private static final String PHYS_PORT_NUM = "physPortNum";
+
+ private static final String NULL_OBJECT_MSG = "VirtualPort cannot be null";
+ private static final String MISSING_MEMBER_MSG = " member is required in VirtualPort";
+ private static final String INVALID_VIRTUAL_DEVICE = " is not a valid VirtualDevice";
+
+ @Override
+ public ObjectNode encode(VirtualPort vPort, CodecContext context) {
+ checkNotNull(vPort, NULL_OBJECT_MSG);
+
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(NETWORK_ID, vPort.networkId().toString())
+ .put(DEVICE_ID, vPort.element().id().toString())
+ .put(PORT_NUM, vPort.number().toString())
+ .put(PHYS_DEVICE_ID, vPort.realizedBy().deviceId().toString())
+ .put(PHYS_PORT_NUM, vPort.realizedBy().port().toString());
+
+ return result;
+ }
+
+ @Override
+ public VirtualPort decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
+ DeviceId dId = DeviceId.deviceId(extractMember(DEVICE_ID, json));
+
+ VirtualNetworkService vnetService = context.getService(VirtualNetworkService.class);
+ Set<VirtualDevice> vDevs = vnetService.getVirtualDevices(nId);
+ VirtualDevice vDev = vDevs.stream()
+ .filter(virtualDevice -> virtualDevice.id().equals(dId))
+ .findFirst().orElse(null);
+ nullIsIllegal(vDev, dId.toString() + INVALID_VIRTUAL_DEVICE);
+
+ PortNumber portNum = PortNumber.portNumber(extractMember(PORT_NUM, json));
+ DeviceId physDId = DeviceId.deviceId(extractMember(PHYS_DEVICE_ID, json));
+ PortNumber physPortNum = PortNumber.portNumber(extractMember(PHYS_PORT_NUM, json));
+
+ ConnectPoint realizedBy = new ConnectPoint(physDId, physPortNum);
+ return new DefaultVirtualPort(nId, vDev, portNum, realizedBy);
+ }
+
+ private String extractMember(String key, ObjectNode json) {
+ return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/package-info.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/package-info.java
new file mode 100644
index 0000000..8999592
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/codec/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Network virtualization data model codecs.
+ */
+package org.onosproject.incubator.net.virtual.codec;
\ No newline at end of file
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/AbstractVirtualListenerManager.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/AbstractVirtualListenerManager.java
new file mode 100644
index 0000000..57dfe0c
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/AbstractVirtualListenerManager.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.event;
+
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.event.Event;
+import org.onosproject.event.EventDeliveryService;
+import org.onosproject.event.EventListener;
+import org.onosproject.event.ListenerRegistry;
+import org.onosproject.event.ListenerService;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.incubator.net.virtual.VnetService;
+
+/**
+ * Basis for virtual event components which need to export listener mechanism.
+ */
+public abstract class AbstractVirtualListenerManager
+ <E extends Event, L extends EventListener<E>>
+ implements ListenerService<E, L>, VnetService {
+
+ protected final NetworkId networkId;
+ protected final VirtualNetworkService manager;
+ protected final ServiceDirectory serviceDirectory;
+
+ protected EventDeliveryService eventDispatcher;
+
+ private ListenerRegistry<E, L> listenerRegistry;
+
+ private VirtualListenerRegistryManager listenerManager =
+ VirtualListenerRegistryManager.getInstance();
+
+ public AbstractVirtualListenerManager(VirtualNetworkService manager,
+ NetworkId networkId,
+ Class<? extends Event> eventClass) {
+ this.manager = manager;
+ this.networkId = networkId;
+ this.serviceDirectory = manager.getServiceDirectory();
+
+ //Set default event delivery service by default
+ this.eventDispatcher = serviceDirectory.get(EventDeliveryService.class);
+
+ //Initialize and reference to the listener registry
+ this.listenerRegistry = listenerManager.getRegistry(networkId, eventClass);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void addListener(L listener) {
+ listenerRegistry.addListener(listener);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void removeListener(L listener) {
+ listenerRegistry.removeListener(listener);
+ }
+
+ /**
+ * Safely posts the specified event to the local event dispatcher.
+ * If there is no event dispatcher or if the event is null, this method
+ * is a noop.
+ *
+ * @param event event to be posted; may be null
+ */
+ protected void post(E event) {
+ if (event != null && eventDispatcher != null) {
+ VirtualEvent<E> vEvent =
+ new VirtualEvent<E>(networkId, VirtualEvent.Type.POSTED, event);
+ eventDispatcher.post(vEvent);
+ }
+ }
+
+ @Override
+ public NetworkId networkId() {
+ return this.networkId;
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualEvent.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualEvent.java
new file mode 100644
index 0000000..bbba983
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.event;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.event.Event;
+import org.onosproject.incubator.net.virtual.NetworkId;
+
+/**
+ * Base class for virtual network event that encapsulates a normal event.
+ */
+public class VirtualEvent<E extends Event>
+ extends AbstractEvent<VirtualEvent.Type, E> {
+
+ private NetworkId networkId;
+
+ /**
+ * Type of virtual network events.
+ */
+ public enum Type {
+ /**
+ * A new virtual event has been posted.
+ */
+ POSTED
+ }
+
+ protected VirtualEvent(NetworkId networkId, Type type, E subject) {
+ super(type, subject);
+ this.networkId = networkId;
+ }
+
+ protected VirtualEvent(NetworkId networkId, Type type, E subject, long time) {
+ super(type, subject, time);
+ this.networkId = networkId;
+ }
+
+ public NetworkId networkId() {
+ return networkId;
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualListenerRegistryManager.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualListenerRegistryManager.java
new file mode 100644
index 0000000..55210dd
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualListenerRegistryManager.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.event;
+
+import com.google.common.collect.Maps;
+import org.onosproject.event.Event;
+import org.onosproject.event.EventSink;
+import org.onosproject.event.ListenerRegistry;
+import org.onosproject.incubator.net.virtual.NetworkId;
+
+import java.util.Map;
+
+/**
+ * Base implementation of an virtual event sink and a registry capable of tracking
+ * listeners and dispatching events to them as part of event sink processing.
+ */
+public final class VirtualListenerRegistryManager
+ implements EventSink<VirtualEvent> {
+
+ private Map<NetworkId, Map<Class<? extends Event>, ListenerRegistry>>
+ listenerMapByNetwork = Maps.newConcurrentMap();
+
+ ListenerRegistry lastStart;
+
+ // non-instantiable (except for our Singleton)
+ private VirtualListenerRegistryManager() {
+
+ }
+
+ public static VirtualListenerRegistryManager getInstance() {
+ return SingletonHelper.INSTANCE;
+ }
+
+ public ListenerRegistry getRegistry(NetworkId networkId,
+ Class<? extends Event> eventClass) {
+ Map<Class<? extends Event>, ListenerRegistry> listenerMapByEvent =
+ listenerMapByNetwork.get(networkId);
+
+ if (listenerMapByEvent == null) {
+ listenerMapByEvent = Maps.newConcurrentMap();
+ listenerMapByNetwork.putIfAbsent(networkId, listenerMapByEvent);
+ }
+
+ ListenerRegistry listenerRegistry = listenerMapByEvent.get(eventClass);
+
+ if (listenerRegistry == null) {
+ listenerRegistry = new ListenerRegistry();
+ listenerMapByEvent.putIfAbsent(eventClass, listenerRegistry);
+ }
+
+ return listenerRegistry;
+ }
+
+ @Override
+ public void process(VirtualEvent event) {
+ NetworkId networkId = event.networkId();
+ Event originalEvent = (Event) event.subject();
+
+ ListenerRegistry listenerRegistry =
+ listenerMapByNetwork.get(networkId).get(originalEvent.getClass());
+ if (listenerRegistry != null) {
+ listenerRegistry.process(originalEvent);
+ lastStart = listenerRegistry;
+ }
+ }
+
+ @Override
+ public void onProcessLimit() {
+ lastStart.onProcessLimit();
+ }
+
+ /**
+ * Prevents object instantiation from external.
+ */
+ private static final class SingletonHelper {
+ private static final String ILLEGAL_ACCESS_MSG =
+ "Should not instantiate this class.";
+ private static final VirtualListenerRegistryManager INSTANCE =
+ new VirtualListenerRegistryManager();
+
+ private SingletonHelper() {
+ throw new IllegalAccessError(ILLEGAL_ACCESS_MSG);
+ }
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/package-info.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/package-info.java
new file mode 100644
index 0000000..448df90
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/event/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Virtual network event delivery subsystem interfaces & supporting abstractions.
+ */
+package org.onosproject.incubator.net.virtual.event;
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/VirtualIntentCompiler.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/VirtualIntentCompiler.java
new file mode 100644
index 0000000..e76bf6e
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/VirtualIntentCompiler.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.intent.Intent;
+
+import java.util.List;
+
+/**
+ * Abstraction of a compiler which is capable of taking an intent
+ * and translating it to other, potentially installable, intents for virtual networks.
+ *
+ * @param <T> the type of intent
+ */
+@Beta
+public interface VirtualIntentCompiler<T extends Intent> {
+ /**
+ * Compiles the specified intent into other intents.
+ *
+ * @param networkId network identifier
+ * @param intent intent to be compiled
+ * @param installable previous compilation result; optional
+ * @return list of resulting intents
+ * @throws VirtualIntentException if issues are encountered while compiling the intent
+ */
+ List<Intent> compile(NetworkId networkId, T intent, List<Intent> installable);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/VirtualIntentException.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/VirtualIntentException.java
new file mode 100644
index 0000000..49cb908
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/VirtualIntentException.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.intent;
+
+public class VirtualIntentException extends RuntimeException {
+
+ //FIXME: how to obatin UID?
+ private static final long serialVersionUID = 1907263634145241319L;
+
+ /**
+ * Constructs an exception with no message and no underlying cause.
+ */
+ public VirtualIntentException() {
+ }
+
+ /**
+ * Constructs an exception with the specified message.
+ *
+ * @param message the message describing the specific nature of the error
+ */
+ public VirtualIntentException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with the specified message and the underlying cause.
+ *
+ * @param message the message describing the specific nature of the error
+ * @param cause the underlying cause of this error
+ */
+ public VirtualIntentException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/package-info.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/package-info.java
new file mode 100644
index 0000000..c5673ac
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/intent/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Set of abstractions for conveying high-level intents for treatment of
+ * selected network traffic by allowing applications to express the
+ * <em>what</em> rather than the <em>how</em> for virtual networks.
+ */
+package org.onosproject.incubator.net.virtual.intent;
\ No newline at end of file
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/package-info.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/package-info.java
new file mode 100644
index 0000000..d9ced32
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Network virtualization data models and services.
+ */
+package org.onosproject.incubator.net.virtual;
\ No newline at end of file
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/AbstractVirtualProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/AbstractVirtualProvider.java
new file mode 100644
index 0000000..bb4ba30
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/AbstractVirtualProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.provider.ProviderId;
+
+public abstract class AbstractVirtualProvider implements VirtualProvider {
+ private final ProviderId providerId;
+
+ /**
+ * Creates a virtual provider with the supplied identifier.
+ *
+ * @param id a virtual provider id
+ */
+ protected AbstractVirtualProvider(ProviderId id) {
+ this.providerId = id;
+ }
+
+ @Override
+ public ProviderId id() {
+ return providerId;
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/AbstractVirtualProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/AbstractVirtualProviderService.java
new file mode 100644
index 0000000..2411e26
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/AbstractVirtualProviderService.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Base implementation of a virtual provider service,
+ * which tracks the provider to which it is issued and can be invalidated.
+ *
+ * @param <P> type of the information provider
+ */
+public abstract class AbstractVirtualProviderService<P extends VirtualProvider>
+ implements VirtualProviderService<P> {
+
+ private boolean isValid = true;
+ private P provider = null;
+
+ /**
+ * Creates a virtual provider service on behalf of the specified provider.
+ *
+ * @param provider provider to which this service is being issued
+ */
+ protected void setProvider(P provider) {
+ this.provider = provider;
+ }
+
+ /**
+ * Invalidates this provider service.
+ */
+ public void invalidate() {
+ isValid = false;
+ }
+
+ /**
+ * Checks the validity of this provider service.
+ *
+ * @throws java.lang.IllegalStateException if the service is no longer valid
+ */
+ public void checkValidity() {
+ checkState(isValid, "Provider service is no longer valid");
+ }
+
+ @Override
+ public P provider() {
+ return provider;
+ }
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/InternalRoutingAlgorithm.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/InternalRoutingAlgorithm.java
new file mode 100644
index 0000000..c17f0d9
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/InternalRoutingAlgorithm.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Path;
+
+/**
+ * Abstraction of an embedding algorithm used for embedding virtual objects
+ * into the underlying physical network.
+ */
+public interface InternalRoutingAlgorithm {
+ /**
+ * Find a route between two connect points (i.e. ports)
+ * according to the own logic.
+ *
+ * @param src A start point
+ * @param dst A sink point
+ * @return The path between src and dst calculated from the algorithm
+ */
+ Path findPath(ConnectPoint src, ConnectPoint dst);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualDeviceProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualDeviceProvider.java
new file mode 100644
index 0000000..9191eaf
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualDeviceProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.PortNumber;
+
+/**
+ * Abstraction of a virtual device information provider.
+ */
+public interface VirtualDeviceProvider extends VirtualProvider {
+
+ /**
+ * Notifies the provider of a mastership role change for the specified
+ * device as decided by the core.
+ *
+ * @param deviceId device identifier
+ * @param newRole newly determined mastership role
+ */
+ void roleChanged(DeviceId deviceId, MastershipRole newRole);
+
+ /**
+ * Indicates whether or not the specified connect points on the underlying
+ * network are traversable.
+ *
+ * @param src source connection point
+ * @param dst destination connection point
+ * @return true if the destination is reachable from the source
+ */
+ boolean isTraversable(ConnectPoint src, ConnectPoint dst);
+
+ /**
+ * Indicates whether or not the all physical devices mapped by the given
+ * virtual device are reachable.
+ *
+ * @param deviceId device identifier
+ * @return true if the all physical devices are reachable, false otherwise
+ */
+ boolean isReachable(DeviceId deviceId);
+
+ /**
+ * Administratively enables or disables a port.
+ *
+ * @param deviceId device identifier
+ * @param portNumber port number
+ * @param enable true if port is to be enabled, false to disable
+ */
+ void changePortState(DeviceId deviceId, PortNumber portNumber,
+ boolean enable);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualDeviceProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualDeviceProviderService.java
new file mode 100644
index 0000000..e2d584c
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualDeviceProviderService.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.incubator.net.virtual.VirtualPortDescription;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.device.PortStatistics;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Service through which virtual device providers can inject virtual device
+ * information into the core.
+ */
+public interface VirtualDeviceProviderService
+ extends VirtualProviderService<VirtualDeviceProvider> {
+
+ /**
+ * Updates information about all ports of a device. It is up to the core to
+ * determine what has changed.
+ *
+ * @param deviceId identity of the device
+ * @param portDescs list of virtual device ports
+ */
+ void updatePorts(DeviceId deviceId, List<VirtualPortDescription> portDescs);
+
+ /**
+ * Notifies the core about port status change of a single port.
+ *
+ * @param deviceId identity of the device
+ * @param portDesc description of the virtual port that changed
+ */
+ void portStatusChanged(DeviceId deviceId, VirtualPortDescription portDesc);
+
+ /**
+ * Notifies the core about the result of a RoleRequest sent to a device.
+ *
+ * @param deviceId identity of the device
+ * @param requested mastership role that was requested by the node
+ * @param response mastership role the switch accepted
+ */
+ void receivedRoleReply(DeviceId deviceId, MastershipRole requested,
+ MastershipRole response);
+
+ /**
+ * Updates statistics about all ports of a device.
+ *
+ * @param deviceId identity of the device
+ * @param portStatistics list of device port statistics
+ */
+ void updatePortStatistics(DeviceId deviceId,
+ Collection<PortStatistics> portStatistics);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProvider.java
new file mode 100644
index 0000000..8a4ec34
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProvider.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+
+/**
+ * Abstraction of a virtual flow rule provider.
+ * This provider virtualizes and de-virtualizes FlowRule.
+ * See {@link org.onosproject.net.flow.FlowRule}.
+ */
+public interface VirtualFlowRuleProvider extends VirtualProvider {
+
+ /**
+ * Instructs the provider to apply the specified flow rules to their
+ * respective virtual devices.
+ *
+ * @param networkId the identity of the virtual network where this rule applies
+ * @param flowRules one or more flow rules
+ */
+ void applyFlowRule(NetworkId networkId, FlowRule... flowRules);
+
+ /**
+ * Instructs the provider to remove the specified flow rules to their
+ * respective virtual devices.
+ *
+ * @param networkId the identity of the virtual network where this rule applies
+ * @param flowRules one or more flow rules
+ */
+ void removeFlowRule(NetworkId networkId, FlowRule... flowRules);
+
+ /**
+ * Installs a batch of flow rules. Each flowrule is associated to an
+ * operation which results in either addition, removal or modification.
+ *
+ * @param networkId the identity of the virtual network where this rule applies
+ * @param batch a batch of flow rules
+ */
+ void executeBatch(NetworkId networkId, FlowRuleBatchOperation batch);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProviderService.java
new file mode 100644
index 0000000..065af9c
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProviderService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.CompletedBatchOperation;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.TableStatisticsEntry;
+
+import java.util.List;
+
+/**
+ * Service through which virtual flow rule providers can inject information into
+ * the core.
+ */
+public interface VirtualFlowRuleProviderService
+ extends VirtualProviderService<VirtualFlowRuleProvider> {
+
+ /**
+ * Signals that a flow rule that was previously installed has been removed.
+ *
+ * @param flowEntry removed flow entry
+ */
+ void flowRemoved(FlowEntry flowEntry);
+
+ /**
+ * Pushes the collection of flow entries currently applied on the given
+ * virtual device.
+ *
+ * @param deviceId device identifier
+ * @param flowEntries collection of flow rules
+ */
+ void pushFlowMetrics(DeviceId deviceId, Iterable<FlowEntry> flowEntries);
+
+ /**
+ * Pushes the collection of flow entries currently applied on the given
+ * device without flowMissing process.
+ *
+ * @param deviceId device identifier
+ * @param flowEntries collection of flow rules
+ */
+ void pushFlowMetricsWithoutFlowMissing(DeviceId deviceId, Iterable<FlowEntry> flowEntries);
+
+ /**
+ * Pushes the collection of table statistics entries currently extracted
+ * from the given virtual device.
+ *
+ * @param deviceId device identifier
+ * @param tableStatsEntries collection of flow table statistics entries
+ */
+ void pushTableStatistics(DeviceId deviceId, List<TableStatisticsEntry> tableStatsEntries);
+
+ /**
+ * Indicates to the core that the requested batch operation has
+ * been completed.
+ *
+ * @param batchId the batch which was processed
+ * @param operation the resulting outcome of the operation
+ */
+ void batchOperationCompleted(long batchId, CompletedBatchOperation operation);
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualGroupProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualGroupProvider.java
new file mode 100644
index 0000000..72d68c3
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualGroupProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.group.GroupOperations;
+
+/**
+ * Abstraction of group provider for virtual network.
+ */
+public interface VirtualGroupProvider extends VirtualProvider {
+ /**
+ * Performs a batch of group operation in the specified virtual device
+ * with the specified parameters.
+ *
+ * @param networkId the identity of the virtual network where this rule applies
+ * @param deviceId device identifier on which the batch of group
+ * operations to be executed
+ * @param groupOps immutable list of group operation
+ */
+ void performGroupOperation(NetworkId networkId, DeviceId deviceId,
+ GroupOperations groupOps);
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualGroupProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualGroupProviderService.java
new file mode 100644
index 0000000..0fdaca8
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualGroupProviderService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupOperation;
+
+import java.util.Collection;
+
+/**
+ * Service through which Group providers can inject information into
+ * the virtual network core.
+ */
+public interface VirtualGroupProviderService
+ extends VirtualProviderService<VirtualGroupProvider> {
+ /**
+ * Notifies core if any failure from data plane during group operations.
+ *
+ * @param deviceId the device ID
+ * @param operation offended group operation
+ */
+ void groupOperationFailed(DeviceId deviceId, GroupOperation operation);
+
+ /**
+ * Pushes the collection of group detected in the data plane along
+ * with statistics.
+ *
+ * @param deviceId device identifier
+ * @param groupEntries collection of group entries as seen in data plane
+ */
+ void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries);
+
+ /**
+ * Notifies store of group failovers.
+ *
+ * @param failoverGroups failover groups in which a failover has occurred
+ */
+ void notifyOfFailovers(Collection<Group> failoverGroups);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualMeterProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualMeterProvider.java
new file mode 100644
index 0000000..6ac80e4
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualMeterProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.MeterOperation;
+import org.onosproject.net.meter.MeterOperations;
+
+/**
+ * Abstraction of a Meter provider for virtual network.
+ */
+public interface VirtualMeterProvider extends VirtualProvider {
+ /**
+ * Performs a batch of meter operation on the specified virtual device
+ * with the specified parameters.
+ *
+ * @param networkId the identity of the virtual network where this rule applies
+ * @param deviceId device identifier on which the batch of group
+ * operations to be executed
+ * @param meterOps immutable list of meter operation
+ */
+ void performMeterOperation(NetworkId networkId, DeviceId deviceId,
+ MeterOperations meterOps);
+
+
+ /**
+ * Performs a meter operation on the specified vitual device with the
+ * specified parameters.
+ *
+ * @param networkId the identity of the virtual network where this rule applies
+ * @param deviceId device identifier on which the batch of group
+ * operations to be executed
+ * @param meterOp a meter operation
+ */
+ void performMeterOperation(NetworkId networkId, DeviceId deviceId,
+ MeterOperation meterOp);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualMeterProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualMeterProviderService.java
new file mode 100644
index 0000000..46e4a7d
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualMeterProviderService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterFailReason;
+import org.onosproject.net.meter.MeterFeatures;
+import org.onosproject.net.meter.MeterOperation;
+
+import java.util.Collection;
+
+/**
+ * Service through which meter providers can inject information
+ * into the virtual network subsystem core.
+ */
+public interface VirtualMeterProviderService
+ extends VirtualProviderService<VirtualMeterProvider> {
+ /**
+ * Notifies the core that a meter operation failed for a
+ * specific reason.
+ *
+ * @param operation the failed operation
+ * @param reason the failure reason
+ */
+ void meterOperationFailed(MeterOperation operation, MeterFailReason reason);
+
+ /**
+ * Pushes the collection of meters observed on the data plane as
+ * well as their associated statistics.
+ *
+ * @param deviceId a device id
+ * @param meterEntries a collection of meter entries
+ */
+ void pushMeterMetrics(DeviceId deviceId, Collection<Meter> meterEntries);
+
+ /**
+ * Pushes the meter features collected from the device.
+ *
+ * @param deviceId the device Id
+ * @param meterfeatures the meter features
+ */
+ void pushMeterFeatures(DeviceId deviceId,
+ MeterFeatures meterfeatures);
+
+ /**
+ * Delete meter features collected from the device.
+ *
+ * @param deviceId the device id
+ */
+ void deleteMeterFeatures(DeviceId deviceId);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProvider.java
new file mode 100644
index 0000000..038d4b3
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Entity capable of providing traffic isolation constructs for use in
+ * implementation of virtual devices and virtual links.
+ */
+public interface VirtualNetworkProvider extends Provider {
+
+ /**
+ * Indicates whether or not the specified connect points on the underlying
+ * network are traversable/reachable.
+ *
+ * @param src source connection point
+ * @param dst destination connection point
+ * @return true if the destination is reachable from the source
+ */
+ boolean isTraversable(ConnectPoint src, ConnectPoint dst);
+
+ // TODO: Further enhance this interface to support the virtual intent programming across this boundary.
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProviderRegistry.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProviderRegistry.java
new file mode 100644
index 0000000..6fbb1a7
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of a virtual network provider registry.
+ */
+public interface VirtualNetworkProviderRegistry
+ extends ProviderRegistry<VirtualNetworkProvider, VirtualNetworkProviderService> {
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProviderService.java
new file mode 100644
index 0000000..ee7d9a6
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualNetworkProviderService.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.provider.ProviderService;
+
+import java.util.Set;
+
+/**
+ * Service through which virtual network providers can inject information into
+ * the core.
+ */
+public interface VirtualNetworkProviderService extends ProviderService<VirtualNetworkProvider> {
+
+ /**
+ * Set of separate topology clusters expressed in terms of connect points which
+ * belong to the same SCC of the underlying topology.
+ *
+ * @param clusters set of sets of mutually reachable connection points;
+ * the outer sets are not mutually reachable
+ */
+ void topologyChanged(Set<Set<ConnectPoint>> clusters);
+
+ // TBD: Is the above sufficient to determine health/viability of virtual entities based on
+ // clustering (SCC) of the physical ones?
+
+ /**
+ * This method is used to notify the VirtualNetwork service that a tunnel is now ACTIVE.
+ *
+ * @param networkId network identifier
+ * @param src source connection point
+ * @param dst destination connection point
+ * @param tunnelId tunnel identifier
+ */
+ void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId);
+
+ /**
+ * This method is used to notify the VirtualNetwork service that a tunnel is now
+ * FAILED or INACTIVE.
+ *
+ * @param networkId network identifier
+ * @param src source connection point
+ * @param dst destination connection point
+ * @param tunnelId tunnel identifier
+ */
+ void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId);
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualPacketProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualPacketProvider.java
new file mode 100644
index 0000000..4cc8d80
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualPacketProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.packet.OutboundPacket;
+
+/**
+ * Abstraction of a virtual packet provider capable of emitting packets
+ * from virtual network core services to the underlay network.
+ * This provider de-virtualizes and virtualize PacketContext.
+ */
+public interface VirtualPacketProvider extends VirtualProvider {
+ /**
+ * Emits the specified outbound packet onto the underlay physical network.
+ * This provider maps the requested packets for physical network.
+ *
+ * @param networkId the virtual network ID
+ * @param packet outbound packet in the context of virtual network
+ */
+ void emit(NetworkId networkId, OutboundPacket packet);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualPacketProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualPacketProviderService.java
new file mode 100644
index 0000000..3c2b4c2
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualPacketProviderService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.packet.PacketContext;
+
+/**
+ * Entity capable of processing inbound packets for virtual networks.
+ */
+public interface VirtualPacketProviderService
+ extends VirtualProviderService<VirtualPacketProvider> {
+
+ /**
+ * Submits inbound packet context for processing to virtual network core.
+ * This processing will be done synchronously, i.e. run-to-completion.
+ * This context is translated with virtual concepts.
+ *
+ * @param context inbound packet context
+ */
+ void processPacket(PacketContext context);
+
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProvider.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProvider.java
new file mode 100644
index 0000000..ac0dfb6
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Abstraction of a provider of information about virtual network environment.
+ * The role of virtual providers is to translate virtual objects into physical
+ * objects, vice versa.
+ */
+public interface VirtualProvider {
+
+ /**
+ * Returns the provider identifier.
+ *
+ * @return provider identification
+ */
+ ProviderId id();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderRegistryService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderRegistryService.java
new file mode 100644
index 0000000..546463c
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderRegistryService.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.provider;
+
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Set;
+
+/**
+ * Registry for tracking information providers with the core.
+ */
+public interface VirtualProviderRegistryService {
+
+ /**
+ * Registers the supplied virtual provider.
+ *
+ * @param virtualProvider a virtual provider to be registered
+ * @throws java.lang.IllegalArgumentException if the provider is registered already
+ */
+ void registerProvider(VirtualProvider virtualProvider);
+
+ /**
+ * Unregisters the supplied virtual provider.
+ * As a result the previously issued virtual provider service will be invalidated
+ * and any subsequent invocations of its methods may throw
+ * {@link java.lang.IllegalStateException}.
+ * <p>
+ * Unregistering a virtual provider that has not been previously registered results
+ * in a no-op.
+ * </p>
+ *
+ * @param virtualProvider a virtual provider to be unregistered
+ */
+ void unregisterProvider(VirtualProvider virtualProvider);
+
+ /**
+ * Registers the supplied virtual provider.
+ *
+ * @param networkId a virtual network identifier
+ * @param virtualProviderService a virtual provider service to be registered
+ */
+ void registerProviderService(NetworkId networkId,
+ VirtualProviderService virtualProviderService);
+
+ /**
+ * Unregisters the supplied virtual provider service.
+ *
+ * @param networkId a virtual network identifier
+ * @param virtualProviderService a virtual provider service to be unregistered
+ */
+ void unregisterProviderService(NetworkId networkId,
+ VirtualProviderService virtualProviderService);
+
+ /**
+ * Returns a set of currently registered virtual provider identities.
+ *
+ * @return set of virtual provider identifiers
+ */
+ Set<ProviderId> getProviders();
+
+ /**
+ * Returns a set of currently registered virtual provider identities
+ * corresponding to the requested providerService.
+ *
+ * @param virtualProviderService a virtual provider service
+ * @return set of virtual provider identifiers
+ */
+ Set<ProviderId> getProvidersByService(VirtualProviderService virtualProviderService);
+
+ /**
+ * Returns the virtual provider registered with the specified provider ID or null
+ * if none is found for the given provider family and default fall-back is
+ * not supported.
+ *
+ * @param providerId provider identifier
+ * @return provider
+ */
+ VirtualProvider getProvider(ProviderId providerId);
+
+ /**
+ * Returns the virtual provider for the specified device ID based on URI scheme.
+ *
+ * @param deviceId virtual device identifier
+ * @return provider bound to the URI scheme
+ */
+ VirtualProvider getProvider(DeviceId deviceId);
+
+ /**
+ * Returns the virtual provider registered with the specified scheme.
+ *
+ * @param scheme provider scheme
+ * @return provider
+ */
+ VirtualProvider getProvider(String scheme);
+
+ /**
+ * Returns a virtual provider service corresponding to
+ * the virtual network and provider class type.
+ *
+ * @param networkId a virtual network identifier
+ * @param providerClass a type of virtual provider
+ * @return a virtual provider service
+ */
+ VirtualProviderService getProviderService(NetworkId networkId,
+ Class<? extends VirtualProvider> providerClass);
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderService.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderService.java
new file mode 100644
index 0000000..8ad378f
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderService.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.provider;
+
+/**
+ * Abstraction of a service through which virtual providers can inject information
+ * about the network environment into the virtual core.
+ *
+ * @param <P> type of the information virtual provider
+ */
+
+public interface VirtualProviderService<P extends VirtualProvider> {
+ /**
+ * Returns the virtual provider to which this service has been issued.
+ *
+ * @return virtual provider to which this service has been assigned
+ */
+ P provider();
+}
diff --git a/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/package-info.java b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/package-info.java
new file mode 100644
index 0000000..8d360d5
--- /dev/null
+++ b/apps/virtual/api/src/main/java/org/onosproject/incubator/net/virtual/provider/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Network virtualization provider interfaces and implementation.
+ */
+package org.onosproject.incubator.net.virtual.provider;
\ No newline at end of file
diff --git a/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/ComparatorsTest.java b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/ComparatorsTest.java
new file mode 100644
index 0000000..ba208bf
--- /dev/null
+++ b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/ComparatorsTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.junit.Test;
+import org.onlab.packet.ChassisId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.TenantId;
+import org.onosproject.net.provider.ProviderId;
+
+import static org.junit.Assert.*;
+import static org.onosproject.incubator.net.virtual.Comparators.VIRTUAL_DEVICE_COMPARATOR;
+import static org.onosproject.incubator.net.virtual.Comparators.VIRTUAL_NETWORK_COMPARATOR;
+import static org.onosproject.incubator.net.virtual.Comparators.VIRTUAL_PORT_COMPARATOR;
+import static org.onosproject.net.DeviceId.deviceId;
+
+public class ComparatorsTest {
+ private static final ProviderId PID = new ProviderId("of", "foo");
+ private static final DeviceId DID = deviceId("of:foo");
+ private static final String MFR = "whitebox";
+ private static final String HW = "1.1.x";
+ private static final String SW = "3.9.1";
+ private static final String SN = "43311-12345";
+ private static final ChassisId CID = new ChassisId();
+
+ @Test
+ public void testVirtualNetworkComparator() {
+ assertNotEquals(0, VIRTUAL_NETWORK_COMPARATOR.compare(network(10, "tenantID"), network(10, "tenantID1")));
+ assertNotEquals(0, VIRTUAL_NETWORK_COMPARATOR.compare(network(10, "tenantID"), network(15, "tenantID1")));
+ assertNotEquals(0, VIRTUAL_NETWORK_COMPARATOR.compare(network(15, "tenantID1"), network(10, "tenantID1")));
+ assertNotEquals(0, VIRTUAL_NETWORK_COMPARATOR.compare(network(15, "tenantID"), network(10, "tenantID1")));
+ }
+
+ private VirtualNetwork network(int networkID, String tenantID) {
+ return new DefaultVirtualNetwork(NetworkId.networkId(networkID), TenantId.tenantId(tenantID));
+ }
+
+ @Test
+ public void testVirtualDeviceComparator() {
+ assertEquals(0, VIRTUAL_DEVICE_COMPARATOR.compare(vd(0, "of:foo"), vd(0, "of:foo")));
+ assertEquals(0, VIRTUAL_DEVICE_COMPARATOR.compare(vd(3, "of:foo"), vd(0, "of:foo")));
+ assertNotEquals(0, VIRTUAL_DEVICE_COMPARATOR.compare(vd(0, "of:bar"), vd(0, "of:foo")));
+ assertNotEquals(0, VIRTUAL_DEVICE_COMPARATOR.compare(vd(3, "of:bar"), vd(0, "of:foo")));
+ }
+
+ private VirtualDevice vd(int netID, String devID) {
+ return new DefaultVirtualDevice(NetworkId.networkId(netID), DeviceId.deviceId(devID));
+ }
+
+ @Test
+ public void testVirtualPortComparator() {
+ assertEquals(0, VIRTUAL_PORT_COMPARATOR.compare(vPort(2), vPort(2)));
+ assertEquals(4, VIRTUAL_PORT_COMPARATOR.compare(vPort(900), vPort(5)));
+ assertEquals(-8, VIRTUAL_PORT_COMPARATOR.compare(vPort(0), vPort(8)));
+ }
+
+ private VirtualPort vPort(int portNumber) {
+ return new DefaultVirtualPort(NetworkId.networkId(20),
+ new DefaultDevice(PID, DID, null, MFR, HW, SW, SN, CID),
+ PortNumber.portNumber(portNumber),
+ new ConnectPoint(DID, PortNumber.portNumber(900)));
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualDeviceTest.java b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualDeviceTest.java
new file mode 100644
index 0000000..22be664
--- /dev/null
+++ b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualDeviceTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.TestDeviceParams;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test of the default virtual device model entity.
+ */
+public class DefaultVirtualDeviceTest extends TestDeviceParams {
+
+ /**
+ * Checks that the DefaultVirtualDevice class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultVirtualDevice.class);
+ }
+
+ @Test
+ public void testEquality() {
+ DefaultVirtualDevice device1 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID1);
+ DefaultVirtualDevice device2 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID1);
+ DefaultVirtualDevice device3 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID2);
+ DefaultVirtualDevice device4 =
+ new DefaultVirtualDevice(NetworkId.networkId(1), DID1);
+
+ new EqualsTester().addEqualityGroup(device1, device2).addEqualityGroup(device3)
+ .addEqualityGroup(device4).testEquals();
+ }
+}
diff --git a/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualHostTest.java b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualHostTest.java
new file mode 100644
index 0000000..7fcf70d
--- /dev/null
+++ b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualHostTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.TestDeviceParams;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test of the default virtual host model entity.
+ */
+public class DefaultVirtualHostTest extends TestDeviceParams {
+
+ /**
+ * Checks that the DefaultVirtualHost class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultVirtualHost.class);
+ }
+
+ /**
+ * Tests the DefaultVirtualHost equality method.
+ */
+ @Test
+ public void testEquality() {
+ DefaultVirtualHost host1 =
+ new DefaultVirtualHost(NetworkId.networkId(0), HID1, MAC1, VLAN1, LOC1, IPSET1);
+ DefaultVirtualHost host2 =
+ new DefaultVirtualHost(NetworkId.networkId(0), HID1, MAC1, VLAN1, LOC1, IPSET1);
+ DefaultVirtualHost host3 =
+ new DefaultVirtualHost(NetworkId.networkId(0), HID2, MAC1, VLAN1, LOC1, IPSET1);
+ DefaultVirtualHost host4 =
+ new DefaultVirtualHost(NetworkId.networkId(1), HID2, MAC1, VLAN1, LOC1, IPSET1);
+
+ new EqualsTester().addEqualityGroup(host1, host2).addEqualityGroup(host3)
+ .addEqualityGroup(host4).testEquals();
+ }
+}
diff --git a/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualLinkTest.java b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualLinkTest.java
new file mode 100644
index 0000000..b96290f
--- /dev/null
+++ b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualLinkTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.TestDeviceParams;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test of the default virtual link model entity.
+ */
+public class DefaultVirtualLinkTest extends TestDeviceParams {
+
+ /**
+ * Checks that the DefaultVirtualLink class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultVirtualLink.class);
+ }
+
+ /**
+ * Tests the DefaultVirtualLink Builder to ensure that the src cannot be null.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testBuilderNullSrc() {
+ DefaultVirtualDevice device1 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID1);
+ DefaultVirtualDevice device2 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID2);
+ ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+ ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+ DefaultVirtualLink.builder()
+ .src(null)
+ .build();
+ }
+
+ /**
+ * Tests the DefaultVirtualLink Builder to ensure that the dst cannot be null.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testBuilderNullDst() {
+ DefaultVirtualDevice device1 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID1);
+ DefaultVirtualDevice device2 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID2);
+ ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+ ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+ DefaultVirtualLink.builder()
+ .dst(null)
+ .build();
+ }
+
+ /**
+ * Tests the DefaultVirtualLink Builder to ensure that the networkId cannot be null.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testBuilderNullNetworkId() {
+ DefaultVirtualDevice device1 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID1);
+ DefaultVirtualDevice device2 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID2);
+ ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+ ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+ DefaultVirtualLink.builder()
+ .networkId(null)
+ .build();
+ }
+
+ /**
+ * Tests the DefaultVirtualLink equality method.
+ */
+ @Test
+ public void testEquality() {
+ DefaultVirtualDevice device1 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID1);
+ DefaultVirtualDevice device2 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID2);
+ ConnectPoint src = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+ ConnectPoint dst = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+ VirtualLink link1 = DefaultVirtualLink.builder()
+ .networkId(NetworkId.networkId(0))
+ .src(src)
+ .dst(dst)
+ .tunnelId(TunnelId.valueOf("1"))
+ .build();
+ VirtualLink link2 = DefaultVirtualLink.builder()
+ .networkId(NetworkId.networkId(0))
+ .src(src)
+ .dst(dst)
+ .tunnelId(TunnelId.valueOf("1"))
+ .build();
+ VirtualLink link3 = DefaultVirtualLink.builder()
+ .networkId(NetworkId.networkId(0))
+ .src(src)
+ .dst(dst)
+ .tunnelId(TunnelId.valueOf("2"))
+ .build();
+ VirtualLink link4 = DefaultVirtualLink.builder()
+ .networkId(NetworkId.networkId(1))
+ .src(src)
+ .dst(dst)
+ .tunnelId(TunnelId.valueOf("3"))
+ .build();
+
+ new EqualsTester().addEqualityGroup(link1, link2).addEqualityGroup(link3)
+ .addEqualityGroup(link4).testEquals();
+ }
+}
diff --git a/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetworkTest.java b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetworkTest.java
new file mode 100644
index 0000000..7ff4715
--- /dev/null
+++ b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualNetworkTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.TenantId;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test of the default virtual network model entity.
+ */
+public class DefaultVirtualNetworkTest {
+ final String tenantIdValue1 = "TENANT_ID1";
+ final String tenantIdValue2 = "TENANT_ID2";
+
+ /**
+ * Checks that the DefaultVirtualNetwork class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultVirtualNetwork.class);
+ }
+
+ @Test
+ public void testEquality() {
+ DefaultVirtualNetwork network1 =
+ new DefaultVirtualNetwork(NetworkId.networkId(0), TenantId.tenantId(tenantIdValue1));
+ DefaultVirtualNetwork network2 =
+ new DefaultVirtualNetwork(NetworkId.networkId(0), TenantId.tenantId(tenantIdValue1));
+ DefaultVirtualNetwork network3 =
+ new DefaultVirtualNetwork(NetworkId.networkId(0), TenantId.tenantId(tenantIdValue2));
+ DefaultVirtualNetwork network4 =
+ new DefaultVirtualNetwork(NetworkId.networkId(1), TenantId.tenantId(tenantIdValue2));
+
+ new EqualsTester().addEqualityGroup(network1, network2).addEqualityGroup(network3)
+ .addEqualityGroup(network4).testEquals();
+ }
+}
diff --git a/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualPortTest.java b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualPortTest.java
new file mode 100644
index 0000000..61ba611
--- /dev/null
+++ b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/DefaultVirtualPortTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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 com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.TestDeviceParams;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test of the default virtual port model entity.
+ */
+public class DefaultVirtualPortTest extends TestDeviceParams {
+ /**
+ * Checks that the DefaultVirtualPort class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultVirtualPort.class);
+ }
+
+ @Test
+ public void testEquality() {
+ DefaultVirtualDevice device1 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID1);
+ DefaultVirtualDevice device2 =
+ new DefaultVirtualDevice(NetworkId.networkId(0), DID2);
+
+ ConnectPoint cpA = new ConnectPoint(device1.id(), PortNumber.portNumber(1));
+ ConnectPoint cpB = new ConnectPoint(device1.id(), PortNumber.portNumber(2));
+ ConnectPoint cpC = new ConnectPoint(device2.id(), PortNumber.portNumber(2));
+
+ DefaultVirtualPort port1 =
+ new DefaultVirtualPort(NetworkId.networkId(0), device1,
+ PortNumber.portNumber(1), cpA);
+ DefaultVirtualPort port2 =
+ new DefaultVirtualPort(NetworkId.networkId(0), device1,
+ PortNumber.portNumber(1), cpA);
+ DefaultVirtualPort port3 =
+ new DefaultVirtualPort(NetworkId.networkId(0), device1,
+ PortNumber.portNumber(2), cpB);
+ DefaultVirtualPort port4 =
+ new DefaultVirtualPort(NetworkId.networkId(1), device2,
+ PortNumber.portNumber(2), cpC);
+
+
+ new EqualsTester().addEqualityGroup(port1, port2).addEqualityGroup(port3)
+ .addEqualityGroup(port4).testEquals();
+ }
+}
diff --git a/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/codec/VirtualHostCodecTest.java b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/codec/VirtualHostCodecTest.java
new file mode 100644
index 0000000..043e434
--- /dev/null
+++ b/apps/virtual/api/src/test/java/org/onosproject/incubator/net/virtual/codec/VirtualHostCodecTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.codec;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+import java.util.stream.IntStream;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.codec.impl.MockCodecContext;
+import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualHost;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.NetTestTools;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isOneOf;
+import static org.hamcrest.Matchers.notNullValue;
+
+/**
+ * Tests VirtualHostCodec class.
+ */
+@Ignore
+public class VirtualHostCodecTest {
+
+ private static final String TEST_IP1 = "1.1.1.1";
+ private static final String TEST_IP2 = "2.2.2.2";
+ private static final String TEST_HOST_ID = "12:34:56:78:90:11/1";
+ private static final String TEST_MAC_ADDRESS = "11:11:22:22:33:33";
+ private static final long TEST_NETWORK_ID = 44L;
+ private static final short TEST_VLAN_ID = (short) 12;
+ private static final ConnectPoint CONNECT_POINT =
+ NetTestTools.connectPoint("d1", 1);
+
+ @Test
+ public void testEncode() {
+ MockCodecContext context = new MockCodecContext();
+ NetworkId networkId = NetworkId.networkId(TEST_NETWORK_ID);
+ HostId id = NetTestTools.hid(TEST_HOST_ID);
+ MacAddress mac = MacAddress.valueOf(TEST_MAC_ADDRESS);
+ VlanId vlan = VlanId.vlanId(TEST_VLAN_ID);
+ HostLocation location =
+ new HostLocation(CONNECT_POINT, 0L);
+ Set<IpAddress> ips = ImmutableSet.of(IpAddress.valueOf(TEST_IP1),
+ IpAddress.valueOf(TEST_IP2));
+ VirtualHost host =
+ new DefaultVirtualHost(networkId, id, mac, vlan, location, ips);
+ JsonCodec<VirtualHost> codec = context.codec(VirtualHost.class);
+ ObjectNode node = codec.encode(host, context);
+
+ assertThat(node.get(VirtualHostCodec.NETWORK_ID).asLong(),
+ is(TEST_NETWORK_ID));
+ assertThat(node.get(VirtualHostCodec.HOST_ID).asText(),
+ is(TEST_HOST_ID));
+ assertThat(node.get(VirtualHostCodec.MAC_ADDRESS).asText(),
+ is(TEST_MAC_ADDRESS));
+ assertThat(node.get(VirtualHostCodec.VLAN).asInt(),
+ is((int) TEST_VLAN_ID));
+ assertThat(node.get(VirtualHostCodec.HOST_LOCATION).get(0).get("elementId").asText(),
+ is(location.deviceId().toString()));
+ assertThat(node.get(VirtualHostCodec.HOST_LOCATION).get(0).get("port").asLong(),
+ is(location.port().toLong()));
+
+ JsonNode jsonIps = node.get(VirtualHostCodec.IP_ADDRESSES);
+ assertThat(jsonIps, notNullValue());
+ assertThat(jsonIps.isArray(), is(true));
+ assertThat(jsonIps.size(), is(ips.size()));
+
+ IntStream.of(0, 1).forEach(index ->
+ assertThat(jsonIps.get(index).asText(),
+ isOneOf(TEST_IP1, TEST_IP2)));
+ }
+
+ @Test
+ public void testDecode() throws IOException {
+ MockCodecContext context = new MockCodecContext();
+ InputStream jsonStream =
+ VirtualHostCodecTest.class.getResourceAsStream("VirtualHost.json");
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ JsonCodec<VirtualHost> codec = context.codec(VirtualHost.class);
+ VirtualHost virtualHost = codec.decode((ObjectNode) json, context);
+ assertThat(virtualHost, notNullValue());
+
+ assertThat(virtualHost.networkId().id(),
+ is(TEST_NETWORK_ID));
+ assertThat(virtualHost.id().toString(),
+ is(NetTestTools.hid(TEST_MAC_ADDRESS + "/12").toString()));
+ assertThat(virtualHost.mac().toString(),
+ is(TEST_MAC_ADDRESS));
+ assertThat(virtualHost.vlan().id(),
+ is((short) TEST_VLAN_ID));
+ assertThat(virtualHost.location().deviceId(),
+ is(CONNECT_POINT.deviceId()));
+ assertThat(virtualHost.location().port().toLong(),
+ is(CONNECT_POINT.port().toLong()));
+
+
+ assertThat(virtualHost.ipAddresses().contains(IpAddress.valueOf(TEST_IP1)),
+ is(true));
+ assertThat(virtualHost.ipAddresses().contains(IpAddress.valueOf(TEST_IP2)),
+ is(true));
+ }
+}
diff --git a/apps/virtual/api/src/test/resources/org/onosproject/incubator/net/virtual/codec/VirtualHost.json b/apps/virtual/api/src/test/resources/org/onosproject/incubator/net/virtual/codec/VirtualHost.json
new file mode 100644
index 0000000..818ce0b
--- /dev/null
+++ b/apps/virtual/api/src/test/resources/org/onosproject/incubator/net/virtual/codec/VirtualHost.json
@@ -0,0 +1,15 @@
+{
+ "networkId": "44",
+ "mac": "11:11:22:22:33:33",
+ "vlan": "12",
+ "ipAddresses": [
+ "1.1.1.1",
+ "2.2.2.2"
+ ],
+ "locations": [
+ {
+ "elementId": "of:d1",
+ "port": "1"
+ }
+ ]
+}