ONOS-4077: REST API's for virtual links.
Change-Id: Idc838f24735e75ad2729393a03dcac4d256239bb
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java b/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java
index 5cfac90..c03a3fa 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java
@@ -28,6 +28,7 @@
import org.onosproject.core.Application;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.Annotations;
@@ -134,6 +135,7 @@
registerCodec(VirtualNetwork.class, new VirtualNetworkCodec());
registerCodec(VirtualDevice.class, new VirtualDeviceCodec());
registerCodec(VirtualPort.class, new VirtualPortCodec());
+ registerCodec(VirtualLink.class, new VirtualLinkCodec());
log.info("Started");
}
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/VirtualLinkCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/VirtualLinkCodec.java
new file mode 100644
index 0000000..54f51e7
--- /dev/null
+++ b/core/common/src/main/java/org/onosproject/codec/impl/VirtualLinkCodec.java
@@ -0,0 +1,65 @@
+package org.onosproject.codec.impl;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualLink;
+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 TUNNEL_ID = "tunnelId";
+
+ private static final String NULL_OBJECT_MSG = "VirtualLink cannot be null";
+ private static final String MISSING_MEMBER_MSG = " member is required in VirtualLink";
+
+ @Override
+ public ObjectNode encode(VirtualLink vLink, CodecContext context) {
+ checkNotNull(vLink, NULL_OBJECT_MSG);
+
+ JsonCodec<Link> codec = context.codec(Link.class);
+ ObjectNode result = codec.encode(vLink, context);
+ result.put(NETWORK_ID, vLink.networkId().toString());
+ // TODO check if tunnelId needs to be part of VirtualLink interface.
+ if (vLink instanceof DefaultVirtualLink) {
+ result.put(TUNNEL_ID, ((DefaultVirtualLink) vLink).tunnelId().toString());
+ }
+ return result;
+ }
+
+ @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)));
+ String tunnelIdStr = json.path(TUNNEL_ID).asText();
+ TunnelId tunnelId = tunnelIdStr != null ? TunnelId.valueOf(tunnelIdStr)
+ : TunnelId.valueOf(0);
+ return new DefaultVirtualLink(nId, link.src(), link.dst(), tunnelId);
+ }
+
+ /**
+ * 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/web/api/src/main/java/org/onosproject/rest/resources/TenantWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/TenantWebResource.java
index 201892a..dc15be5 100755
--- a/web/api/src/main/java/org/onosproject/rest/resources/TenantWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/TenantWebResource.java
@@ -131,7 +131,7 @@
*
* @param stream TenantId JSON stream
* @return TenantId
- * @throws IOException
+ * @throws IOException if unable to parse the request
*/
private TenantId getTenantIdFromJsonStream(InputStream stream) throws IOException {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
@@ -146,11 +146,11 @@
/**
* Get the matching tenant identifier from existing tenant identifiers in system.
*
- * @param vnetAdminSvc
+ * @param vnetAdminSvc virtual network administration service
* @param tidIn tenant identifier
* @return TenantId
*/
- private static TenantId getExistingTenantId(VirtualNetworkAdminService vnetAdminSvc,
+ static TenantId getExistingTenantId(VirtualNetworkAdminService vnetAdminSvc,
TenantId tidIn) {
final TenantId resultTid = vnetAdminSvc
.getTenantIds()
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
index 1ebfe56..8df8722 100755
--- a/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
@@ -18,9 +18,12 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
@@ -38,6 +41,7 @@
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -69,7 +73,6 @@
UriInfo uriInfo;
// VirtualNetwork
- // TODO Query vnets by tenant
/**
* Returns all virtual networks.
@@ -88,6 +91,22 @@
}
/**
+ * Returns the virtual networks with the specified tenant identifier.
+ *
+ * @param tenantId tenant identifier
+ * @return 200 OK, 404 not found
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{tenantId}")
+ public Response getVirtualNetworkById(@PathParam("tenantId") String tenantId) {
+ final TenantId existingTid = TenantWebResource.getExistingTenantId(vnetAdminService,
+ TenantId.tenantId(tenantId));
+ Set<VirtualNetwork> vnets = vnetService.getVirtualNetworks(existingTid);
+ return ok(encodeArray(VirtualNetwork.class, "vnets", vnets)).build();
+ }
+
+ /**
* Creates a virtual network from the JSON input stream.
*
* @param stream TenantId JSON stream
@@ -122,7 +141,7 @@
@DELETE
@Path("{networkId}")
public Response removeVirtualNetwork(@PathParam("networkId") long networkId) {
- final NetworkId nid = NetworkId.networkId(networkId);
+ NetworkId nid = NetworkId.networkId(networkId);
vnetAdminService.removeVirtualNetwork(nid);
return Response.ok().build();
}
@@ -139,7 +158,7 @@
@Produces(MediaType.APPLICATION_JSON)
@Path("{networkId}/devices")
public Response getVirtualDevices(@PathParam("networkId") long networkId) {
- final NetworkId nid = NetworkId.networkId(networkId);
+ NetworkId nid = NetworkId.networkId(networkId);
Set<VirtualDevice> vdevs = vnetService.getVirtualDevices(nid);
return ok(encodeArray(VirtualDevice.class, "devices", vdevs)).build();
}
@@ -154,7 +173,7 @@
* @onos.rsModel VirtualDevice
*/
@POST
- @Path("{networkId}/devices/")
+ @Path("{networkId}/devices")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createVirtualDevice(@PathParam("networkId") long networkId,
@@ -162,15 +181,14 @@
try {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
final VirtualDevice vdevReq = codec(VirtualDevice.class).decode(jsonTree, this);
- JsonNode specifiedRegionId = jsonTree.get("networkId");
- if (specifiedRegionId != null &&
- specifiedRegionId.asLong() != (networkId)) {
+ JsonNode specifiedNetworkId = jsonTree.get("networkId");
+ if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
throw new IllegalArgumentException(INVALID_FIELD + "networkId");
}
final VirtualDevice vdevRes = vnetAdminService.createVirtualDevice(vdevReq.networkId(),
vdevReq.id());
UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
- .path("vnets").path(specifiedRegionId.asText())
+ .path("vnets").path(specifiedNetworkId.asText())
.path("devices").path(vdevRes.id().toString());
return Response
.created(locationBuilder.build())
@@ -191,8 +209,8 @@
@Path("{networkId}/devices/{deviceId}")
public Response removeVirtualDevice(@PathParam("networkId") long networkId,
@PathParam("deviceId") String deviceId) {
- final NetworkId nid = NetworkId.networkId(networkId);
- final DeviceId did = DeviceId.deviceId(deviceId);
+ NetworkId nid = NetworkId.networkId(networkId);
+ DeviceId did = DeviceId.deviceId(deviceId);
vnetAdminService.removeVirtualDevice(nid, did);
return Response.ok().build();
}
@@ -211,7 +229,7 @@
@Path("{networkId}/devices/{deviceId}/ports")
public Response getVirtualPorts(@PathParam("networkId") long networkId,
@PathParam("deviceId") String deviceId) {
- final NetworkId nid = NetworkId.networkId(networkId);
+ NetworkId nid = NetworkId.networkId(networkId);
Iterable<VirtualPort> vports = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
return ok(encodeArray(VirtualPort.class, "ports", vports)).build();
}
@@ -238,12 +256,10 @@
// final VirtualPort vportReq = codec(VirtualPort.class).decode(jsonTree, this);
JsonNode specifiedNetworkId = jsonTree.get("networkId");
JsonNode specifiedDeviceId = jsonTree.get("deviceId");
- if (specifiedNetworkId != null &&
- specifiedNetworkId.asLong() != (networkId)) {
+ if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
throw new IllegalArgumentException(INVALID_FIELD + "networkId");
}
- if (specifiedDeviceId != null &&
- !specifiedDeviceId.asText().equals(virtDeviceId)) {
+ if (specifiedDeviceId == null || !specifiedDeviceId.asText().equals(virtDeviceId)) {
throw new IllegalArgumentException(INVALID_FIELD + "deviceId");
}
JsonNode specifiedPortNum = jsonTree.get("portNum");
@@ -283,13 +299,129 @@
public Response removeVirtualPort(@PathParam("networkId") long networkId,
@PathParam("deviceId") String deviceId,
@PathParam("portNum") long portNum) {
- final NetworkId nid = NetworkId.networkId(networkId);
+ NetworkId nid = NetworkId.networkId(networkId);
vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId),
PortNumber.portNumber(portNum));
return Response.ok().build();
}
- // TODO VirtualLink
+ // VirtualLink
+
+ /**
+ * Returns all virtual network links in a virtual network.
+ *
+ * @param networkId network identifier
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{networkId}/links")
+ public Response getVirtualLinks(@PathParam("networkId") long networkId) {
+ NetworkId nid = NetworkId.networkId(networkId);
+ Set<VirtualLink> vlinks = vnetService.getVirtualLinks(nid);
+ return ok(encodeArray(VirtualLink.class, "links", vlinks)).build();
+ }
+
+ /**
+ * Creates a virtual network link from the JSON input stream.
+ *
+ * @param networkId network identifier
+ * @param stream Virtual device JSON stream
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ * @onos.rsModel VirtualLink
+ */
+ @POST
+ @Path("{networkId}/links")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createVirtualLink(@PathParam("networkId") long networkId,
+ InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ JsonNode specifiedNetworkId = jsonTree.get("networkId");
+ if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
+ throw new IllegalArgumentException(INVALID_FIELD + "networkId");
+ }
+ final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
+ TunnelId tunnelId = TunnelId.valueOf(0);
+ if (vlinkReq instanceof DefaultVirtualLink) {
+ tunnelId = ((DefaultVirtualLink) vlinkReq).tunnelId();
+ }
+ vnetAdminService.createVirtualLink(vlinkReq.networkId(),
+ vlinkReq.src(), vlinkReq.dst(), tunnelId);
+ UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
+ .path("vnets").path(specifiedNetworkId.asText())
+ .path("links");
+ return Response
+ .created(locationBuilder.build())
+ .build();
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Removes the virtual network link from the JSON input stream.
+ *
+ * @param networkId network identifier
+ * @param stream deviceIds JSON stream
+ * @return 200 OK, 404 not found
+ * @onos.rsModel VirtualLink
+ */
+ @DELETE
+ @Path("{networkId}/links")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response removeVirtualLink(@PathParam("networkId") long networkId,
+ InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ JsonNode specifiedNetworkId = jsonTree.get("networkId");
+ if (specifiedNetworkId != null &&
+ specifiedNetworkId.asLong() != (networkId)) {
+ throw new IllegalArgumentException(INVALID_FIELD + "networkId");
+ }
+ final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
+ vnetAdminService.removeVirtualLink(vlinkReq.networkId(),
+ vlinkReq.src(), vlinkReq.dst());
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ return Response.ok().build();
+ }
+
+ /**
+ * Removes the virtual network link from the JSON input stream.
+ *
+ * @param networkId network identifier
+ * @param stream deviceIds JSON stream
+ * @return 200 OK, 404 not found
+ * @onos.rsModel VirtualLink
+ */
+
+ @PUT
+ @Path("{networkId}/links/remove")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response removeVirtualLink2(@PathParam("networkId") long networkId,
+ InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ JsonNode specifiedNetworkId = jsonTree.get("networkId");
+ if (specifiedNetworkId != null &&
+ specifiedNetworkId.asLong() != (networkId)) {
+ throw new IllegalArgumentException(INVALID_FIELD + "networkId");
+ }
+ final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
+ vnetAdminService.removeVirtualLink(vlinkReq.networkId(),
+ vlinkReq.src(), vlinkReq.dst());
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ return Response.ok().build();
+ }
/**
* Get the tenant identifier from the JSON stream.
@@ -297,7 +429,7 @@
* @param stream TenantId JSON stream
* @param jsonFieldName field name
* @return JsonNode
- * @throws IOException
+ * @throws IOException if unable to parse the request
*/
private JsonNode getFromJsonStream(InputStream stream, String jsonFieldName) throws IOException {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
diff --git a/web/api/src/main/resources/definitions/VirtualLink.json b/web/api/src/main/resources/definitions/VirtualLink.json
new file mode 100644
index 0000000..2bc7be7
--- /dev/null
+++ b/web/api/src/main/resources/definitions/VirtualLink.json
@@ -0,0 +1,65 @@
+{
+ "type": "object",
+ "title": "vlink",
+ "required": [
+ "networkId",
+ "src",
+ "dst",
+ "type",
+ "state"
+ ],
+ "properties": {
+ "networkId": {
+ "type": "String",
+ "example": "Network identifier"
+ },
+ "src": {
+ "type": "object",
+ "title": "src",
+ "required": [
+ "port",
+ "device"
+ ],
+ "properties": {
+ "port": {
+ "type": "string",
+ "example": "3"
+ },
+ "device": {
+ "type": "string",
+ "example": "of:0000000000000002"
+ }
+ }
+ },
+ "dst": {
+ "type": "object",
+ "title": "dst",
+ "required": [
+ "port",
+ "device"
+ ],
+ "properties": {
+ "port": {
+ "type": "string",
+ "example": "2"
+ },
+ "device": {
+ "type": "string",
+ "example": "of:0000000000000003"
+ }
+ }
+ },
+ "type": {
+ "type": "string",
+ "example": "DIRECT"
+ },
+ "state": {
+ "type": "string",
+ "example": "ACTIVE"
+ },
+ "tunnelId": {
+ "type": "int64",
+ "example": "Tunnel identifier"
+ }
+ }
+}
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
index 72daa8b..58f5ab4 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
@@ -32,16 +32,20 @@
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
+import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
+import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.incubator.net.virtual.VirtualPort;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
@@ -61,6 +65,7 @@
import java.net.HttpURLConnection;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
@@ -80,7 +85,6 @@
private CodecManager codecService;
final HashSet<TenantId> tenantIdSet = new HashSet<>();
- final HashSet<VirtualNetwork> vnetSet = new HashSet<>();
final HashSet<VirtualDevice> vdevSet = new HashSet<>();
final HashSet<VirtualPort> vportSet = new HashSet<>();
@@ -90,6 +94,7 @@
private static final String PORT_NUM = "portNum";
private static final String PHYS_DEVICE_ID = "physDeviceId";
private static final String PHYS_PORT_NUM = "physPortNum";
+ private static final String TUNNEL_ID = "tunnelId";
private final TenantId tenantId1 = TenantId.tenantId("TenantId1");
private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
@@ -106,8 +111,8 @@
private final VirtualNetwork vnet3 = new DefaultVirtualNetwork(networkId3, tenantId3);
private final VirtualNetwork vnet4 = new DefaultVirtualNetwork(networkId4, tenantId3);
- private final DeviceId devId1 = DeviceId.deviceId("devId1");
- private final DeviceId devId2 = DeviceId.deviceId("devId2");
+ private final DeviceId devId1 = DeviceId.deviceId("devid1");
+ private final DeviceId devId2 = DeviceId.deviceId("devid2");
private final DeviceId devId22 = DeviceId.deviceId("dev22");
private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1);
@@ -115,6 +120,7 @@
private final Device dev1 = NetTestTools.device("dev1");
private final Device dev2 = NetTestTools.device("dev2");
+ private final Device dev21 = NetTestTools.device("dev21");
private final Device dev22 = NetTestTools.device("dev22");
Port port1 = new DefaultPort(dev1, portNumber(1), true);
@@ -125,6 +131,15 @@
private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
dev22, portNumber(23), port2);
+ private final ConnectPoint cp11 = NetTestTools.connectPoint(devId1.toString(), 21);
+ private final ConnectPoint cp21 = NetTestTools.connectPoint(devId2.toString(), 22);
+ private final ConnectPoint cp12 = NetTestTools.connectPoint(devId1.toString(), 2);
+ private final ConnectPoint cp22 = NetTestTools.connectPoint(devId2.toString(), 22);
+
+ private final TunnelId tunnelId = TunnelId.valueOf(31);
+ private final VirtualLink vlink1 = new DefaultVirtualLink(networkId3, cp22, cp11, tunnelId);
+ private final VirtualLink vlink2 = new DefaultVirtualLink(networkId3, cp12, cp21, tunnelId);
+
/**
* Sets up the global values for all the tests.
*/
@@ -313,12 +328,9 @@
*/
@Test
public void testGetVirtualNetworksArray() {
+ final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
replay(mockVnetAdminService);
- vnetSet.add(vnet1);
- vnetSet.add(vnet2);
- vnetSet.add(vnet3);
- vnetSet.add(vnet4);
expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
replay(mockVnetService);
@@ -344,6 +356,64 @@
}
/**
+ * Tests the result of the REST API GET for virtual networks with tenant id.
+ */
+ @Test
+ public void testGetVirtualNetworksByTenantId() {
+ final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
+ expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
+ replay(mockVnetAdminService);
+ expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
+ replay(mockVnetService);
+
+ WebTarget wt = target();
+ String response = wt.path("vnets/" + tenantId3.id()).request().get(String.class);
+ assertThat(response, containsString("{\"vnets\":["));
+
+ final JsonObject result = Json.parse(response).asObject();
+ assertThat(result, notNullValue());
+
+ assertThat(result.names(), hasSize(1));
+ assertThat(result.names().get(0), is("vnets"));
+
+ final JsonArray vnetJsonArray = result.get("vnets").asArray();
+ assertThat(vnetJsonArray, notNullValue());
+ assertEquals("Virtual networks array is not the correct size.",
+ vnetSet.size(), vnetJsonArray.size());
+
+ vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
+
+ verify(mockVnetService);
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests the result of the REST API GET for virtual networks with tenant id.
+ */
+ @Test
+ public void testGetVirtualNetworksByNonExistentTenantId() {
+ String tenantIdName = "NON_EXISTENT_TENANT_ID";
+ expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
+ replay(mockVnetAdminService);
+ expect(mockVnetService.getVirtualNetworks(anyObject())).andReturn(ImmutableSet.of()).anyTimes();
+ replay(mockVnetService);
+
+ WebTarget wt = target();
+
+ try {
+ wt.path("vnets/" + tenantIdName)
+ .request()
+ .get(String.class);
+ fail("Get of a non-existent virtual network did not throw an exception");
+ } catch (NotFoundException ex) {
+ assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
+ }
+
+ verify(mockVnetService);
+ verify(mockVnetAdminService);
+ }
+
+ /**
* Tests adding of new virtual network using POST via JSON stream.
*/
@Test
@@ -756,5 +826,243 @@
verify(mockVnetAdminService);
}
- // TODO Tests for Virtual Links
+ // Tests for Virtual Links
+
+ /**
+ * Tests the result of the REST API GET when there are no virtual links.
+ */
+ @Test
+ public void testGetVirtualLinksEmptyArray() {
+ NetworkId networkId = networkId4;
+ expect(mockVnetService.getVirtualLinks(networkId)).andReturn(ImmutableSet.of()).anyTimes();
+ replay(mockVnetService);
+
+ WebTarget wt = target();
+ String location = "vnets/" + networkId.toString() + "/links";
+ String response = wt.path(location).request().get(String.class);
+ assertThat(response, is("{\"links\":[]}"));
+
+ verify(mockVnetService);
+ }
+
+ /**
+ * Tests the result of the REST API GET when virtual links are defined.
+ */
+ @Test
+ public void testGetVirtualLinksArray() {
+ NetworkId networkId = networkId3;
+ final Set<VirtualLink> vlinkSet = ImmutableSet.of(vlink1, vlink2);
+ expect(mockVnetService.getVirtualLinks(networkId)).andReturn(vlinkSet).anyTimes();
+ replay(mockVnetService);
+
+ WebTarget wt = target();
+ String location = "vnets/" + networkId.toString() + "/links";
+ String response = wt.path(location).request().get(String.class);
+ assertThat(response, containsString("{\"links\":["));
+
+ final JsonObject result = Json.parse(response).asObject();
+ assertThat(result, notNullValue());
+
+ assertThat(result.names(), hasSize(1));
+ assertThat(result.names().get(0), is("links"));
+
+ final JsonArray vnetJsonArray = result.get("links").asArray();
+ assertThat(vnetJsonArray, notNullValue());
+ assertEquals("Virtual links array is not the correct size.",
+ vlinkSet.size(), vnetJsonArray.size());
+
+ vlinkSet.forEach(vlink -> assertThat(vnetJsonArray, hasVlink(vlink)));
+
+ verify(mockVnetService);
+ }
+
+ /**
+ * Hamcrest matcher to check that a virtual link representation in JSON matches
+ * the actual virtual link.
+ */
+ public static class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher {
+ private final VirtualLink vlink;
+ private String reason = "";
+
+ public VirtualLinkJsonMatcher(VirtualLink vlinkValue) {
+ super(vlinkValue);
+ vlink = vlinkValue;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonObject jsonLink) {
+ if (!super.matchesSafely(jsonLink)) {
+ return false;
+ }
+ // check NetworkId
+ String jsonNetworkId = jsonLink.get(ID).asString();
+ String networkId = vlink.networkId().toString();
+ if (!jsonNetworkId.equals(networkId)) {
+ reason = ID + " was " + jsonNetworkId;
+ return false;
+ }
+ // check TunnelId
+ String jsonTunnelId = jsonLink.get(TUNNEL_ID).asString();
+ if (jsonTunnelId != null && vlink instanceof DefaultVirtualLink) {
+ String tunnelId = ((DefaultVirtualLink) vlink).tunnelId().toString();
+ if (!jsonTunnelId.equals(tunnelId)) {
+ reason = TUNNEL_ID + " was " + jsonTunnelId;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(reason);
+ }
+ }
+
+ /**
+ * Factory to allocate a virtual link matcher.
+ *
+ * @param vlink virtual link object we are looking for
+ * @return matcher
+ */
+ private static VirtualLinkJsonMatcher matchesVirtualLink(VirtualLink vlink) {
+ return new VirtualLinkJsonMatcher(vlink);
+ }
+
+ /**
+ * Hamcrest matcher to check that a virtual link is represented properly in a JSON
+ * array of links.
+ */
+ private static class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
+ private final VirtualLink vlink;
+ private String reason = "";
+
+ public VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) {
+ vlink = vlinkValue;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonArray json) {
+ final int expectedAttributes = 2;
+
+ for (int jsonLinkIndex = 0; jsonLinkIndex < json.size();
+ jsonLinkIndex++) {
+
+ JsonObject jsonLink = json.get(jsonLinkIndex).asObject();
+
+ if (matchesVirtualLink(vlink).matchesSafely(jsonLink)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(reason);
+ }
+ }
+
+ /**
+ * Factory to allocate a virtual link array matcher.
+ *
+ * @param vlink virtual link object we are looking for
+ * @return matcher
+ */
+ private VirtualLinkJsonArrayMatcher hasVlink(VirtualLink vlink) {
+ return new VirtualLinkJsonArrayMatcher(vlink);
+ }
+
+ /**
+ * Tests adding of new virtual link using POST via JSON stream.
+ */
+ @Test
+ public void testPostVirtualLink() {
+ NetworkId networkId = networkId3;
+ expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11, tunnelId))
+ .andReturn(vlink1);
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target();
+ InputStream jsonStream = VirtualNetworkWebResourceTest.class
+ .getResourceAsStream("post-virtual-link.json");
+ String reqLocation = "vnets/" + networkId.toString() + "/links";
+ Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
+ .post(Entity.json(jsonStream));
+ assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
+
+ String location = response.getLocation().getPath();
+ assertThat(location, Matchers.startsWith("/" + reqLocation));
+
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests adding of a null virtual link using POST via JSON stream.
+ */
+ @Test
+ public void testPostVirtualLinkNullJsonStream() {
+ NetworkId networkId = networkId3;
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target();
+ try {
+ String reqLocation = "vnets/" + networkId.toString() + "/links";
+ wt.path(reqLocation)
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .post(Entity.json(null), String.class);
+ fail("POST of null virtual link did not throw an exception");
+ } catch (BadRequestException ex) {
+ assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
+ }
+
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests removing a virtual link with DELETE request.
+ */
+ @Test
+ public void testDeleteVirtualLink() {
+ NetworkId networkId = networkId3;
+ mockVnetAdminService.removeVirtualLink(networkId, cp22, cp11);
+ expectLastCall();
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target()
+ .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
+ InputStream jsonStream = VirtualNetworkWebResourceTest.class
+ .getResourceAsStream("post-virtual-link.json");
+ String reqLocation = "vnets/" + networkId.toString() + "/links";
+ Response response = wt.path(reqLocation).request().accept(MediaType.APPLICATION_JSON_TYPE)
+ .method("DELETE", Entity.json(jsonStream));
+// Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
+
+// assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+// verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests removing a virtual link with PUT request.
+ */
+ @Test
+ public void testDeleteVirtualLink2() {
+ NetworkId networkId = networkId3;
+ mockVnetAdminService.removeVirtualLink(networkId, cp22, cp11);
+ expectLastCall();
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target()
+ .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
+ InputStream jsonStream = VirtualNetworkWebResourceTest.class
+ .getResourceAsStream("post-virtual-link.json");
+ String reqLocation = "vnets/" + networkId.toString() + "/links/remove";
+ Response response = wt.path(reqLocation).request().accept(MediaType.APPLICATION_JSON_TYPE)
+ .method("PUT", Entity.json(jsonStream));
+
+ assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+ verify(mockVnetAdminService);
+ }
+
+ // All Tests done
}
diff --git a/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-link.json b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-link.json
new file mode 100644
index 0000000..a7c5d26
--- /dev/null
+++ b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-link.json
@@ -0,0 +1,14 @@
+{
+ "networkId": "3",
+ "src": {
+ "device": "of:devid2",
+ "port": "22"
+ },
+ "dst": {
+ "device": "of:devid1",
+ "port": "21"
+ },
+ "type": "VIRTUAL",
+ "state": "ACTIVE",
+ "tunnelId": "31"
+}