Claudine Chiu
Committed by Gerrit Code Review

REST API's for tenants, virtual networks, virtual devices ad virtual ports.

Change-Id: I80abe14a083fce3dc6246118af8874028109388f

REST API's for tenants, virtual networks, virtual devices ad virtual ports.

Change-Id: Ib6c3d69d396e57822bae23f5bf3101c8b9c0b95c
......@@ -26,6 +26,10 @@ import org.onosproject.cluster.ControllerNode;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.JsonCodec;
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.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
......@@ -126,6 +130,10 @@ public class CodecManager implements CodecService {
registerCodec(McastRoute.class, new McastRouteCodec());
registerCodec(DeviceKey.class, new DeviceKeyCodec());
registerCodec(Region.class, new RegionCodec());
registerCodec(TenantId.class, new TenantIdCodec());
registerCodec(VirtualNetwork.class, new VirtualNetworkCodec());
registerCodec(VirtualDevice.class, new VirtualDeviceCodec());
registerCodec(VirtualPort.class, new VirtualPortCodec());
log.info("Started");
}
......
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.codec.impl;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.incubator.net.virtual.TenantId;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Codec for the TenantId class.
*/
public class TenantIdCodec extends JsonCodec<TenantId> {
// JSON field names
private static final String TENANT_ID = "id";
private static final String NULL_TENANT_MSG = "TenantId cannot be null";
private static final String MISSING_MEMBER_MSG = " member is required in TenantId";
@Override
public ObjectNode encode(TenantId tenantId, CodecContext context) {
checkNotNull(tenantId, NULL_TENANT_MSG);
ObjectNode result = context.mapper().createObjectNode()
.put(TENANT_ID, tenantId.id().toString());
return result;
}
@Override
public TenantId decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
return null;
}
TenantId tenantId = TenantId.tenantId(extractMember(TENANT_ID, json));
return tenantId;
}
private String extractMember(String key, ObjectNode json) {
return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.codec.impl;
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(ID, vDev.id().toString())
.put(NETWORK_ID, vDev.networkId().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);
}
private String extractMember(String key, ObjectNode json) {
return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.codec.impl;
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.incubator.net.virtual.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();
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.codec.impl;
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.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import 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().element().id().toString())
.put(PHYS_PORT_NUM, vPort.realizedBy().number().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));
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
Device physDevice = new DefaultDevice(null, physDId,
null, null, null, null, null, null, annotations);
Port realizedBy = new DefaultPort(physDevice, physPortNum, true);
return new DefaultVirtualPort(nId, vDev, portNum, realizedBy);
}
private String extractMember(String key, ObjectNode json) {
return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
}
}
......@@ -22,7 +22,7 @@ import org.onosproject.net.Port;
* Representation of a virtual port.
*/
@Beta
public interface VirtualPort extends Port {
public interface VirtualPort extends VirtualElement, Port {
/**
* Returns the underlying port using which this port is realized.
......
......@@ -47,7 +47,9 @@ public class CoreWebApplication extends AbstractWebApplication {
FlowObjectiveWebResource.class,
MulticastRouteWebResource.class,
DeviceKeyWebResource.class,
RegionsWebResource.class
RegionsWebResource.class,
TenantWebResource.class,
VirtualNetworkWebResource.class
);
}
}
......
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.rest.resources;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import org.onosproject.rest.AbstractWebResource;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.InputStream;
/**
* Query and manage tenants of virtual networks.
*/
@Path("tenants")
public class TenantWebResource extends AbstractWebResource {
private static final String MISSING_TENANTID = "Missing tenant identifier";
private static final String TENANTID_NOT_FOUND = "Tenant identifier not found";
private static final String INVALID_TENANTID = "Invalid tenant identifier ";
@Context
UriInfo uriInfo;
private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class);
/**
* Returns all tenants.
*
* @return 200 OK
* @onos.rsModel TenantIds
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getVirtualNetworkTenants() {
Iterable<TenantId> tenantIds = vnetAdminService.getTenantIds();
return ok(encodeArray(TenantId.class, "tenants", tenantIds)).build();
}
/**
* Creates a tenant with the given tenant identifier.
*
* @param stream TenantId JSON stream
* @return status of the request - CREATED if the JSON is correct,
* BAD_REQUEST if the JSON is invalid
* @onos.rsModel TenantId
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addTenantId(InputStream stream) {
try {
final TenantId tid = getTenantIdFromJsonStream(stream);
vnetAdminService.registerTenantId(tid);
final TenantId resultTid = getExistingTenantId(vnetAdminService, tid);
UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
.path("tenants")
.path(resultTid.id());
return Response
.created(locationBuilder.build())
.build();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Removes the specified tenant with the specified tenant identifier.
*
* @param tenantId tenant identifier
* @return 200 OK, 404 not found
*/
@DELETE
@Path("{tenantId}")
public Response removeTenantId(@PathParam("tenantId") String tenantId) {
final TenantId tid = TenantId.tenantId(tenantId);
final TenantId existingTid = getExistingTenantId(vnetAdminService, tid);
vnetAdminService.unregisterTenantId(existingTid);
return Response.ok().build();
}
/**
* Removes the specified tenant with the specified tenant identifier.
*
* @param stream deviceIds JSON stream
* @return 200 OK, 404 not found
* @onos.rsModel TenantId
*/
@DELETE
public Response removeTenantId(InputStream stream) {
try {
final TenantId tid = getTenantIdFromJsonStream(stream);
vnetAdminService.unregisterTenantId(tid);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
return Response.ok().build();
}
/**
* Get the tenant identifier from the JSON stream.
*
* @param stream TenantId JSON stream
* @return TenantId
* @throws IOException
*/
private TenantId getTenantIdFromJsonStream(InputStream stream) throws IOException {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
JsonNode specifiedTenantId = jsonTree.get("id");
if (specifiedTenantId == null) {
throw new IllegalArgumentException(MISSING_TENANTID);
}
return TenantId.tenantId(specifiedTenantId.asText());
}
/**
* Get the matching tenant identifier from existing tenant identifiers in system.
*
* @param vnetAdminSvc
* @param tidIn tenant identifier
* @return TenantId
*/
private static TenantId getExistingTenantId(VirtualNetworkAdminService vnetAdminSvc,
TenantId tidIn) {
final TenantId resultTid = vnetAdminSvc
.getTenantIds()
.stream()
.filter(tenantId -> tenantId.equals(tidIn))
.findFirst()
.orElseThrow(() -> new ItemNotFoundException(TENANTID_NOT_FOUND));
return resultTid;
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.rest.resources;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
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.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.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.rest.AbstractWebResource;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Query and Manage Virtual Network elements.
*/
@Path("vnets")
public class VirtualNetworkWebResource extends AbstractWebResource {
private static final String MISSING_FIELD = "Missing ";
private static final String INVALID_FIELD = "Invalid ";
private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class);
private final VirtualNetworkService vnetService = get(VirtualNetworkService.class);
@Context
UriInfo uriInfo;
// VirtualNetwork
// TODO Query vnets by tenant
/**
* Returns all virtual networks.
*
* @return 200 OK
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getVirtualNetworks() {
Set<TenantId> tenantIds = vnetAdminService.getTenantIds();
List<VirtualNetwork> allVnets = tenantIds.stream()
.map(tenantId -> vnetService.getVirtualNetworks(tenantId))
.flatMap(Collection::stream)
.collect(Collectors.toList());
return ok(encodeArray(VirtualNetwork.class, "vnets", allVnets)).build();
}
/**
* Creates a virtual network from the JSON input stream.
*
* @param stream TenantId JSON stream
* @return status of the request - CREATED if the JSON is correct,
* BAD_REQUEST if the JSON is invalid
* @onos.rsModel TenantId
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createVirtualNetwork(InputStream stream) {
try {
final TenantId tid = TenantId.tenantId(getFromJsonStream(stream, "id").asText());
VirtualNetwork newVnet = vnetAdminService.createVirtualNetwork(tid);
UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
.path("vnets")
.path(newVnet.id().toString());
return Response
.created(locationBuilder.build())
.build();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Removes the virtual network with the specified network identifier.
*
* @param networkId network identifier
* @return 200 OK, 404 not found
*/
@DELETE
@Path("{networkId}")
public Response removeVirtualNetwork(@PathParam("networkId") long networkId) {
final NetworkId nid = NetworkId.networkId(networkId);
vnetAdminService.removeVirtualNetwork(nid);
return Response.ok().build();
}
// VirtualDevice
/**
* Returns all virtual network devices in a virtual network.
*
* @param networkId network identifier
* @return 200 OK
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{networkId}/devices")
public Response getVirtualDevices(@PathParam("networkId") long networkId) {
final NetworkId nid = NetworkId.networkId(networkId);
Set<VirtualDevice> vdevs = vnetService.getVirtualDevices(nid);
return ok(encodeArray(VirtualDevice.class, "devices", vdevs)).build();
}
/**
* Creates a virtual device 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 VirtualDevice
*/
@POST
@Path("{networkId}/devices/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createVirtualDevice(@PathParam("networkId") long networkId,
InputStream stream) {
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)) {
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("devices").path(vdevRes.id().toString());
return Response
.created(locationBuilder.build())
.build();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Removes the virtual network device from the virtual network.
*
* @param networkId network identifier
* @param deviceId device identifier
* @return 200 OK, 404 not found
*/
@DELETE
@Path("{networkId}/devices/{deviceId}")
public Response removeVirtualDevice(@PathParam("networkId") long networkId,
@PathParam("deviceId") String deviceId) {
final NetworkId nid = NetworkId.networkId(networkId);
final DeviceId did = DeviceId.deviceId(deviceId);
vnetAdminService.removeVirtualDevice(nid, did);
return Response.ok().build();
}
// VirtualPort
/**
* Returns all virtual network ports in a virtual device in a virtual network.
*
* @param networkId network identifier
* @param deviceId virtual device identifier
* @return 200 OK
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{networkId}/devices/{deviceId}/ports")
public Response getVirtualPorts(@PathParam("networkId") long networkId,
@PathParam("deviceId") String deviceId) {
final NetworkId nid = NetworkId.networkId(networkId);
Iterable<VirtualPort> vports = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
return ok(encodeArray(VirtualPort.class, "ports", vports)).build();
}
/**
* Creates a virtual network port in a virtual device in a virtual network.
*
* @param networkId network identifier
* @param virtDeviceId virtual device 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 VirtualPort
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("{networkId}/devices/{deviceId}/ports")
public Response createVirtualPort(@PathParam("networkId") long networkId,
@PathParam("deviceId") String virtDeviceId,
InputStream stream) {
try {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
// 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)) {
throw new IllegalArgumentException(INVALID_FIELD + "networkId");
}
if (specifiedDeviceId != null &&
!specifiedDeviceId.asText().equals(virtDeviceId)) {
throw new IllegalArgumentException(INVALID_FIELD + "deviceId");
}
JsonNode specifiedPortNum = jsonTree.get("portNum");
JsonNode specifiedPhysDeviceId = jsonTree.get("physDeviceId");
JsonNode specifiedPhysPortNum = jsonTree.get("physPortNum");
final NetworkId nid = NetworkId.networkId(networkId);
DeviceId vdevId = DeviceId.deviceId(virtDeviceId);
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
Device physDevice = new DefaultDevice(null, DeviceId.deviceId(specifiedPhysDeviceId.asText()),
null, null, null, null, null, null, annotations);
Port realizedBy = new DefaultPort(physDevice,
PortNumber.portNumber(specifiedPhysPortNum.asText()), true);
VirtualPort vport = vnetAdminService.createVirtualPort(nid, vdevId,
PortNumber.portNumber(specifiedPortNum.asText()), realizedBy);
UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
.path("vnets").path(specifiedNetworkId.asText())
.path("devices").path(specifiedDeviceId.asText())
.path("ports").path(vport.number().toString());
return Response
.created(locationBuilder.build())
.build();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Removes the virtual network port from the virtual device in a virtual network.
*
* @param networkId network identifier
* @param deviceId virtual device identifier
* @param portNum virtual port number
* @return 200 OK, 404 not found
*/
@DELETE
@Path("{networkId}/devices/{deviceId}/ports/{portNum}")
public Response removeVirtualPort(@PathParam("networkId") long networkId,
@PathParam("deviceId") String deviceId,
@PathParam("portNum") long portNum) {
final NetworkId nid = NetworkId.networkId(networkId);
vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId),
PortNumber.portNumber(portNum));
return Response.ok().build();
}
// TODO VirtualLink
/**
* Get the tenant identifier from the JSON stream.
*
* @param stream TenantId JSON stream
* @param jsonFieldName field name
* @return JsonNode
* @throws IOException
*/
private JsonNode getFromJsonStream(InputStream stream, String jsonFieldName) throws IOException {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
JsonNode jsonNode = jsonTree.get(jsonFieldName);
if (jsonNode == null) {
throw new IllegalArgumentException(MISSING_FIELD + jsonFieldName);
}
return jsonNode;
}
}
{
"type": "object",
"title": "TenantId",
"required": [
"id"
],
"properties": {
"id": {
"type": "String",
"example": "Tenant unique identifier"
}
}
}
{
"type": "object",
"title": "tenants",
"required": [
"tenants"
],
"properties": {
"tenants": {
"type": "array",
"xml": {
"name": "tenants",
"wrapped": true
},
"items": {
"type": "object",
"title": "tenant",
"required": [
"id"
],
"properties": {
"id": {
"type": "String",
"example": "Tenant unique identifier"
}
}
}
}
}
}
{
"type": "object",
"title": "vdev",
"required": [
"networkId",
"deviceId"
],
"properties": {
"networkId": {
"type": "String",
"example": "Network identifier"
},
"deviceId": {
"type": "String",
"example": "Device identifier"
}
}
}
{
"type": "object",
"title": "vport",
"required": [
"networkId",
"deviceId",
"portNum",
"physDeviceId",
"physPortNum"
],
"properties": {
"networkId": {
"type": "String",
"example": "Network identifier"
},
"deviceId": {
"type": "String",
"example": "Virtual device identifier"
},
"portNum": {
"type": "String",
"example": "Virtual device port number"
},
"physDeviceId": {
"type": "String",
"example": "Physical device identifier"
},
"physPortNum": {
"type": "String",
"example": "Physical device port number"
}
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.rest.resources;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableSet;
import org.glassfish.jersey.client.ClientProperties;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.HashSet;
import static org.easymock.EasyMock.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* Unit tests for tenant REST APIs.
*/
public class TenantWebResourceTest extends ResourceTest {
private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
final HashSet<TenantId> tenantIdSet = new HashSet<>();
private static final String ID = "id";
private final TenantId tenantId1 = TenantId.tenantId("TenantId1");
private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
/**
* Sets up the global values for all the tests.
*/
@Before
public void setUpTest() {
// Register the services needed for the test
CodecManager codecService = new CodecManager();
codecService.activate();
ServiceDirectory testDirectory =
new TestServiceDirectory()
.add(VirtualNetworkAdminService.class, mockVnetAdminService)
.add(CodecService.class, codecService);
BaseResource.setServiceDirectory(testDirectory);
}
/**
* Hamcrest matcher to check that a tenant id representation in JSON matches
* the actual tenant id.
*/
public static class TenantIdJsonMatcher extends TypeSafeMatcher<JsonObject> {
private final TenantId tenantId;
private String reason = "";
public TenantIdJsonMatcher(TenantId tenantIdValue) {
tenantId = tenantIdValue;
}
@Override
public boolean matchesSafely(JsonObject jsonHost) {
// Check the tenant id
final String jsonId = jsonHost.get(ID).asString();
if (!jsonId.equals(tenantId.id())) {
reason = ID + " " + tenantId.id();
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Factory to allocate a tenant id array matcher.
*
* @param tenantId tenant id object we are looking for
* @return matcher
*/
private static TenantIdJsonMatcher matchesTenantId(TenantId tenantId) {
return new TenantIdJsonMatcher(tenantId);
}
/**
* Hamcrest matcher to check that a tenant id is represented properly in a JSON
* array of tenant ids.
*/
public static class TenantIdJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
private final TenantId tenantId;
private String reason = "";
public TenantIdJsonArrayMatcher(TenantId tenantIdValue) {
tenantId = tenantIdValue;
}
@Override
public boolean matchesSafely(JsonArray json) {
boolean tenantIdFound = false;
final int expectedAttributes = 1;
for (int tenantIdIndex = 0; tenantIdIndex < json.size();
tenantIdIndex++) {
final JsonObject jsonHost = json.get(tenantIdIndex).asObject();
// Only 1 attribute - ID.
if (jsonHost.names().size() < expectedAttributes) {
reason = "Found a tenant id with the wrong number of attributes";
return false;
}
final String jsonDeviceKeyId = jsonHost.get(ID).asString();
if (jsonDeviceKeyId.equals(tenantId.id())) {
tenantIdFound = true;
// We found the correct tenant id, check the tenant id attribute values
assertThat(jsonHost, matchesTenantId(tenantId));
}
}
if (!tenantIdFound) {
reason = "Tenant id " + tenantId.id() + " was not found";
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Factory to allocate a tenant id array matcher.
*
* @param tenantId tenant id object we are looking for
* @return matcher
*/
private static TenantIdJsonArrayMatcher hasTenantId(TenantId tenantId) {
return new TenantIdJsonArrayMatcher(tenantId);
}
/**
* Tests the result of the REST API GET when there are no tenant ids.
*/
@Test
public void testGetTenantsEmptyArray() {
expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetAdminService);
WebTarget wt = target();
String response = wt.path("tenants").request().get(String.class);
assertThat(response, is("{\"tenants\":[]}"));
verify(mockVnetAdminService);
}
/**
* Tests the result of the REST API GET when tenant ids are defined.
*/
@Test
public void testGetTenantIdsArray() {
tenantIdSet.add(tenantId1);
tenantIdSet.add(tenantId2);
tenantIdSet.add(tenantId3);
tenantIdSet.add(tenantId4);
expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes();
replay(mockVnetAdminService);
WebTarget wt = target();
String response = wt.path("tenants").request().get(String.class);
assertThat(response, containsString("{\"tenants\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("tenants"));
final JsonArray tenantIds = result.get("tenants").asArray();
assertThat(tenantIds, notNullValue());
assertEquals("Device keys array is not the correct size.",
tenantIdSet.size(), tenantIds.size());
tenantIdSet.forEach(tenantId -> assertThat(tenantIds, hasTenantId(tenantId)));
verify(mockVnetAdminService);
}
/**
* Tests adding of new tenant id using POST via JSON stream.
*/
@Test
public void testPost() {
mockVnetAdminService.registerTenantId(anyObject());
tenantIdSet.add(tenantId2);
expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes();
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = TenantWebResourceTest.class
.getResourceAsStream("post-tenant.json");
Response response = wt.path("tenants").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("/tenants/" + tenantId2));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null tenant id using POST via JSON stream.
*/
@Test
public void testPostNullTenantId() {
replay(mockVnetAdminService);
WebTarget wt = target();
try {
String response = wt.path("tenants")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null tenant id did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a tenant id with DELETE request.
*/
@Test
public void testDelete() {
expect(mockVnetAdminService.getTenantIds())
.andReturn(ImmutableSet.of(tenantId2)).anyTimes();
mockVnetAdminService.unregisterTenantId(anyObject());
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
Response response = wt.path("tenants/" + tenantId2)
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
/**
* Tests removing a tenant id with DELETE request via JSON stream.
*/
@Test
public void testDeleteViaJson() {
mockVnetAdminService.unregisterTenantId(anyObject());
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
InputStream jsonStream = TenantWebResourceTest.class
.getResourceAsStream("post-tenant.json");
Response response = wt.request().method("DELETE", Entity.json(jsonStream));
// assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
// verify(mockVnetAdminService);
}
/**
* Tests that a DELETE of a non-existent tenant id throws an exception.
*/
@Test
public void testDeleteNonExistentDeviceKey() {
expect(mockVnetAdminService.getTenantIds())
.andReturn(ImmutableSet.of())
.anyTimes();
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
try {
wt.path("tenants/" + "NON_EXISTENT_TENANT_ID")
.request()
.delete(String.class);
fail("Delete of a non-existent tenant did not throw an exception");
} catch (NotFoundException ex) {
assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
}
verify(mockVnetAdminService);
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.rest.resources;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.glassfish.jersey.client.ClientProperties;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
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.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.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.HashSet;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import static org.easymock.EasyMock.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.onosproject.net.PortNumber.portNumber;
/**
* Unit tests for virtual network REST APIs.
*/
public class VirtualNetworkWebResourceTest extends ResourceTest {
private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class);
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<>();
private static final String ID = "networkId";
private static final String TENANT_ID = "tenantId";
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 final TenantId tenantId1 = TenantId.tenantId("TenantId1");
private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
private final NetworkId networkId1 = NetworkId.networkId(1);
private final NetworkId networkId2 = NetworkId.networkId(2);
private final NetworkId networkId3 = NetworkId.networkId(3);
private final NetworkId networkId4 = NetworkId.networkId(4);
private final VirtualNetwork vnet1 = new DefaultVirtualNetwork(networkId1, tenantId3);
private final VirtualNetwork vnet2 = new DefaultVirtualNetwork(networkId2, tenantId3);
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 devId22 = DeviceId.deviceId("dev22");
private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1);
private final VirtualDevice vdev2 = new DefaultVirtualDevice(networkId3, devId2);
private final Device dev1 = NetTestTools.device("dev1");
private final Device dev2 = NetTestTools.device("dev2");
private final Device dev22 = NetTestTools.device("dev22");
Port port1 = new DefaultPort(dev1, portNumber(1), true);
Port port2 = new DefaultPort(dev2, portNumber(2), true);
private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
dev22, portNumber(22), port1);
private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
dev22, portNumber(23), port2);
/**
* Sets up the global values for all the tests.
*/
@Before
public void setUpTest() {
// Register the services needed for the test
codecService = new CodecManager();
codecService.activate();
ServiceDirectory testDirectory =
new TestServiceDirectory()
.add(VirtualNetworkAdminService.class, mockVnetAdminService)
.add(VirtualNetworkService.class, mockVnetService)
.add(CodecService.class, codecService);
BaseResource.setServiceDirectory(testDirectory);
}
/**
* Hamcrest matcher to check that a virtual network entity representation in JSON matches
* the actual virtual network entity.
*/
public static class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> {
private final T vnetEntity;
private List<String> jsonFieldNames;
private String reason = "";
private BiFunction<T, String, String> getValue; // get vnetEntity's value
public JsonObjectMatcher(T vnetEntityValue,
List<String> jsonFieldNames1,
BiFunction<T, String, String> getValue1) {
vnetEntity = vnetEntityValue;
jsonFieldNames = jsonFieldNames1;
getValue = getValue1;
}
@Override
public boolean matchesSafely(JsonObject jsonHost) {
return jsonFieldNames
.stream()
.allMatch(s -> checkField(jsonHost, s, getValue.apply(vnetEntity, s)));
}
private boolean checkField(JsonObject jsonHost, String jsonFieldName,
String objectValue) {
final String jsonValue = jsonHost.get(jsonFieldName).asString();
if (!jsonValue.equals(objectValue)) {
reason = jsonFieldName + " " + objectValue;
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Factory to allocate a virtual network id array matcher.
*
* @param obj virtual network id object we are looking for
* @return matcher
*/
/**
* Factory to allocate a virtual network entity matcher.
*
* @param obj virtual network object we are looking for
* @param jsonFieldNames JSON field names to check against
* @param getValue function to retrieve value from virtual network object
* @param <T>
* @return JsonObjectMatcher
*/
private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames,
BiFunction<T, String, String> getValue) {
return new JsonObjectMatcher(obj, jsonFieldNames, getValue);
}
/**
* Hamcrest matcher to check that a virtual network entity is represented properly in a JSON
* array of virtual network entities.
*/
public static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> {
private final T vnetEntity;
private String reason = "";
private Function<T, String> getKey; // gets vnetEntity's key
private BiPredicate<T, JsonObject> checkKey; // check vnetEntity's key with JSON rep'n
private List<String> jsonFieldNames; // field/property names
private BiFunction<T, String, String> getValue; // get vnetEntity's value
public JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1,
BiPredicate<T, JsonObject> checkKey1,
List<String> jsonFieldNames1,
BiFunction<T, String, String> getValue1) {
vnetEntity = vnetEntityValue;
getKey = getKey1;
checkKey = checkKey1;
jsonFieldNames = jsonFieldNames1;
getValue = getValue1;
}
@Override
public boolean matchesSafely(JsonArray json) {
boolean itemFound = false;
final int expectedAttributes = jsonFieldNames.size();
for (int jsonArrayIndex = 0; jsonArrayIndex < json.size();
jsonArrayIndex++) {
final JsonObject jsonHost = json.get(jsonArrayIndex).asObject();
if (jsonHost.names().size() < expectedAttributes) {
reason = "Found a virtual network with the wrong number of attributes";
return false;
}
if (checkKey != null && checkKey.test(vnetEntity, jsonHost)) {
itemFound = true;
assertThat(jsonHost, matchesVnetEntity(vnetEntity, jsonFieldNames, getValue));
}
}
if (!itemFound) {
reason = getKey.apply(vnetEntity) + " was not found";
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Array matcher for VirtualNetwork.
*/
public static class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> {
public VnetJsonArrayMatcher(VirtualNetwork vnetIn) {
super(vnetIn,
vnet -> "Virtual network " + vnet.id().toString(),
(vnet, jsonObject) -> {
return jsonObject.get(ID).asString().equals(vnet.id().toString()); },
ImmutableList.of(ID, TENANT_ID),
(vnet, s) -> {
return s.equals(ID) ? vnet.id().toString()
: s.equals(TENANT_ID) ? vnet.tenantId().toString()
: null;
}
);
}
}
/**
* Factory to allocate a virtual network array matcher.
*
* @param vnet virtual network object we are looking for
* @return matcher
*/
private VnetJsonArrayMatcher hasVnet(VirtualNetwork vnet) {
return new VnetJsonArrayMatcher(vnet);
}
// Tests for Virtual Networks
/**
* Tests the result of the REST API GET when there are no virtual networks.
*/
@Test
public void testGetVirtualNetworksEmptyArray() {
expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetAdminService);
expect(mockVnetService.getVirtualNetworks(tenantId4)).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String response = wt.path("vnets").request().get(String.class);
assertThat(response, is("{\"vnets\":[]}"));
verify(mockVnetService);
verify(mockVnetAdminService);
}
/**
* Tests the result of the REST API GET when virtual networks are defined.
*/
@Test
public void testGetVirtualNetworksArray() {
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);
WebTarget wt = target();
String response = wt.path("vnets").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 adding of new virtual network using POST via JSON stream.
*/
@Test
public void testPostVirtualNetwork() {
expect(mockVnetAdminService.createVirtualNetwork(tenantId2)).andReturn(vnet1);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = TenantWebResourceTest.class
.getResourceAsStream("post-tenant.json");
Response response = wt.path("vnets").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("/vnets/" + vnet1.id().toString()));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null virtual network using POST via JSON stream.
*/
@Test
public void testPostVirtualNetworkNullTenantId() {
replay(mockVnetAdminService);
WebTarget wt = target();
try {
String response = wt.path("vnets")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null virtual network did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a virtual network with DELETE request.
*/
@Test
public void testDeleteVirtualNetwork() {
mockVnetAdminService.removeVirtualNetwork(anyObject());
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
Response response = wt.path("vnets/" + "2")
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
/**
* Tests that a DELETE of a non-existent virtual network throws an exception.
*/
@Test
public void testDeleteNetworkNonExistentNetworkId() {
expect(mockVnetAdminService.getTenantIds())
.andReturn(ImmutableSet.of())
.anyTimes();
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
try {
wt.path("vnets/" + "NON_EXISTENT_NETWORK_ID")
.request()
.delete(String.class);
fail("Delete of a non-existent virtual network did not throw an exception");
} catch (NotFoundException ex) {
assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
}
verify(mockVnetAdminService);
}
// Tests for Virtual Device
/**
* Tests the result of the REST API GET when there are no virtual devices.
*/
@Test
public void testGetVirtualDevicesEmptyArray() {
NetworkId networkId = networkId4;
expect(mockVnetService.getVirtualDevices(networkId)).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString() + "/devices";
String response = wt.path(location).request().get(String.class);
assertThat(response, is("{\"devices\":[]}"));
verify(mockVnetService);
}
/**
* Tests the result of the REST API GET when virtual devices are defined.
*/
@Test
public void testGetVirtualDevicesArray() {
NetworkId networkId = networkId3;
vdevSet.add(vdev1);
vdevSet.add(vdev2);
expect(mockVnetService.getVirtualDevices(networkId)).andReturn(vdevSet).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString() + "/devices";
String response = wt.path(location).request().get(String.class);
assertThat(response, containsString("{\"devices\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("devices"));
final JsonArray vnetJsonArray = result.get("devices").asArray();
assertThat(vnetJsonArray, notNullValue());
assertEquals("Virtual devices array is not the correct size.",
vdevSet.size(), vnetJsonArray.size());
vdevSet.forEach(vdev -> assertThat(vnetJsonArray, hasVdev(vdev)));
verify(mockVnetService);
}
/**
* Array matcher for VirtualDevice.
*/
public static class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> {
public VdevJsonArrayMatcher(VirtualDevice vdevIn) {
super(vdevIn,
vdev -> "Virtual device " + vdev.networkId().toString()
+ " " + vdev.id().toString(),
(vdev, jsonObject) -> {
return jsonObject.get(ID).asString().equals(vdev.networkId().toString())
&& jsonObject.get(DEVICE_ID).asString().equals(vdev.id().toString()); },
ImmutableList.of(ID, DEVICE_ID),
(vdev, s) -> {
return s.equals(ID) ? vdev.networkId().toString()
: s.equals(DEVICE_ID) ? vdev.id().toString()
: null;
}
);
}
}
/**
* Factory to allocate a virtual device array matcher.
*
* @param vdev virtual device object we are looking for
* @return matcher
*/
private VdevJsonArrayMatcher hasVdev(VirtualDevice vdev) {
return new VdevJsonArrayMatcher(vdev);
}
/**
* Tests adding of new virtual device using POST via JSON stream.
*/
@Test
public void testPostVirtualDevice() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
expect(mockVnetAdminService.createVirtualDevice(networkId, deviceId)).andReturn(vdev2);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = VirtualNetworkWebResourceTest.class
.getResourceAsStream("post-virtual-device.json");
String reqLocation = "vnets/" + networkId.toString() + "/devices";
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 + "/" + vdev2.id().toString()));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null virtual device using POST via JSON stream.
*/
@Test
public void testPostVirtualDeviceNullJsonStream() {
NetworkId networkId = networkId3;
replay(mockVnetAdminService);
WebTarget wt = target();
try {
String reqLocation = "vnets/" + networkId.toString() + "/devices";
String response = wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null virtual device did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a virtual device with DELETE request.
*/
@Test
public void testDeleteVirtualDevice() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
mockVnetAdminService.removeVirtualDevice(networkId, deviceId);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
String reqLocation = "vnets/" + networkId.toString() + "/devices/" + deviceId.toString();
Response response = wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
// Tests for Virtual Ports
/**
* Tests the result of the REST API GET when there are no virtual ports.
*/
@Test
public void testGetVirtualPortsEmptyArray() {
NetworkId networkId = networkId4;
DeviceId deviceId = devId2;
expect(mockVnetService.getVirtualPorts(networkId, deviceId))
.andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
String response = wt.path(location).request().get(String.class);
assertThat(response, is("{\"ports\":[]}"));
verify(mockVnetService);
}
/**
* Tests the result of the REST API GET when virtual ports are defined.
*/
@Test
public void testGetVirtualPortsArray() {
NetworkId networkId = networkId3;
DeviceId deviceId = dev22.id();
vportSet.add(vport23);
vportSet.add(vport22);
expect(mockVnetService.getVirtualPorts(networkId, deviceId)).andReturn(vportSet).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
String response = wt.path(location).request().get(String.class);
assertThat(response, containsString("{\"ports\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("ports"));
final JsonArray vnetJsonArray = result.get("ports").asArray();
assertThat(vnetJsonArray, notNullValue());
assertEquals("Virtual ports array is not the correct size.",
vportSet.size(), vnetJsonArray.size());
vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport)));
verify(mockVnetService);
}
/**
* Array matcher for VirtualPort.
*/
public static class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> {
public VportJsonArrayMatcher(VirtualPort vportIn) {
super(vportIn,
vport -> "Virtual port " + vport.networkId().toString() + " "
+ vport.element().id().toString() + " " + vport.number().toString(),
(vport, jsonObject) -> {
return jsonObject.get(ID).asString().equals(vport.networkId().toString())
&& jsonObject.get(PORT_NUM).asString().equals(vport.number().toString())
&& jsonObject.get(DEVICE_ID).asString().equals(vport.element().id().toString()); },
ImmutableList.of(ID, DEVICE_ID, PORT_NUM, PHYS_DEVICE_ID, PHYS_PORT_NUM),
(vport, s) -> {
return s.equals(ID) ? vport.networkId().toString()
: s.equals(DEVICE_ID) ? vport.element().id().toString()
: s.equals(PORT_NUM) ? vport.number().toString()
: s.equals(PHYS_DEVICE_ID) ? vport.realizedBy().element().id().toString()
: s.equals(PHYS_PORT_NUM) ? vport.realizedBy().number().toString()
: null;
}
);
}
}
/**
* Factory to allocate a virtual port array matcher.
*
* @param vport virtual port object we are looking for
* @return matcher
*/
private VportJsonArrayMatcher hasVport(VirtualPort vport) {
return new VportJsonArrayMatcher(vport);
}
/**
* Tests adding of new virtual port using POST via JSON stream.
*/
@Test
public void testPostVirtualPort() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId22;
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"),
null, null, null, null, null, null, annotations);
Port port1 = new DefaultPort(physDevice, portNumber(1), true);
expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), port1))
.andReturn(vport22);
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = VirtualNetworkWebResourceTest.class
.getResourceAsStream("post-virtual-port.json");
String reqLocation = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null virtual port using POST via JSON stream.
*/
@Test
public void testPostVirtualPortNullJsonStream() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
replay(mockVnetAdminService);
WebTarget wt = target();
try {
String reqLocation = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
String response = wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null virtual port did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a virtual port with DELETE request.
*/
@Test
public void testDeleteVirtualPort() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
PortNumber portNum = portNumber(2);
mockVnetAdminService.removeVirtualPort(networkId, deviceId, portNum);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
String reqLocation = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
Response response = wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
// TODO Tests for Virtual Links
}
{
"networkId": "3",
"deviceId": "dev22",
"portNum": "22",
"physDeviceId": "dev1",
"physPortNum": "1"
}