blob: 252ca5395856e00e33faaf90131762437dd68194 [file] [log] [blame]
Claudine Chiufb8b8162016-04-01 23:50:51 +00001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Claudine Chiufb8b8162016-04-01 23:50:51 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.rest.resources;
18
19import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import org.onosproject.incubator.net.virtual.NetworkId;
22import org.onosproject.incubator.net.virtual.TenantId;
23import org.onosproject.incubator.net.virtual.VirtualDevice;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000024import org.onosproject.incubator.net.virtual.VirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000025import org.onosproject.incubator.net.virtual.VirtualNetwork;
26import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
27import org.onosproject.incubator.net.virtual.VirtualNetworkService;
28import org.onosproject.incubator.net.virtual.VirtualPort;
29import org.onosproject.net.DefaultAnnotations;
30import org.onosproject.net.DefaultDevice;
31import org.onosproject.net.DefaultPort;
32import org.onosproject.net.Device;
33import org.onosproject.net.DeviceId;
34import org.onosproject.net.Port;
35import org.onosproject.net.PortNumber;
36import org.onosproject.rest.AbstractWebResource;
37
38import javax.ws.rs.Consumes;
39import javax.ws.rs.DELETE;
40import javax.ws.rs.GET;
41import javax.ws.rs.POST;
42import javax.ws.rs.Path;
43import javax.ws.rs.PathParam;
44import javax.ws.rs.Produces;
45import javax.ws.rs.core.Context;
46import javax.ws.rs.core.MediaType;
47import javax.ws.rs.core.Response;
48import javax.ws.rs.core.UriBuilder;
49import javax.ws.rs.core.UriInfo;
50import java.io.IOException;
51import java.io.InputStream;
52import java.util.Collection;
53import java.util.List;
54import java.util.Set;
55import java.util.stream.Collectors;
56
57/**
58 * Query and Manage Virtual Network elements.
59 */
60@Path("vnets")
61public class VirtualNetworkWebResource extends AbstractWebResource {
62
63 private static final String MISSING_FIELD = "Missing ";
64 private static final String INVALID_FIELD = "Invalid ";
65
66 private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class);
67 private final VirtualNetworkService vnetService = get(VirtualNetworkService.class);
68
69 @Context
70 UriInfo uriInfo;
71
72 // VirtualNetwork
Claudine Chiufb8b8162016-04-01 23:50:51 +000073
74 /**
75 * Returns all virtual networks.
76 *
77 * @return 200 OK
Claudine Chiu1decd532016-04-19 18:30:01 +000078 * @onos.rsModel VirtualNetworks
Claudine Chiufb8b8162016-04-01 23:50:51 +000079 */
80 @GET
81 @Produces(MediaType.APPLICATION_JSON)
82 public Response getVirtualNetworks() {
83 Set<TenantId> tenantIds = vnetAdminService.getTenantIds();
84 List<VirtualNetwork> allVnets = tenantIds.stream()
85 .map(tenantId -> vnetService.getVirtualNetworks(tenantId))
86 .flatMap(Collection::stream)
87 .collect(Collectors.toList());
88 return ok(encodeArray(VirtualNetwork.class, "vnets", allVnets)).build();
89 }
90
91 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000092 * Returns the virtual networks with the specified tenant identifier.
93 *
94 * @param tenantId tenant identifier
95 * @return 200 OK, 404 not found
Claudine Chiu1decd532016-04-19 18:30:01 +000096 * @onos.rsModel VirtualNetworks
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000097 */
98 @GET
99 @Produces(MediaType.APPLICATION_JSON)
100 @Path("{tenantId}")
101 public Response getVirtualNetworkById(@PathParam("tenantId") String tenantId) {
102 final TenantId existingTid = TenantWebResource.getExistingTenantId(vnetAdminService,
Brian Stanke9a108972016-04-11 15:25:17 -0400103 TenantId.tenantId(tenantId));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000104 Set<VirtualNetwork> vnets = vnetService.getVirtualNetworks(existingTid);
105 return ok(encodeArray(VirtualNetwork.class, "vnets", vnets)).build();
106 }
107
108 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000109 * Creates a virtual network from the JSON input stream.
110 *
Claudine Chiu1decd532016-04-19 18:30:01 +0000111 * @param stream tenant identifier JSON stream
Claudine Chiufb8b8162016-04-01 23:50:51 +0000112 * @return status of the request - CREATED if the JSON is correct,
113 * BAD_REQUEST if the JSON is invalid
114 * @onos.rsModel TenantId
115 */
116 @POST
117 @Consumes(MediaType.APPLICATION_JSON)
118 @Produces(MediaType.APPLICATION_JSON)
119 public Response createVirtualNetwork(InputStream stream) {
120 try {
121 final TenantId tid = TenantId.tenantId(getFromJsonStream(stream, "id").asText());
122 VirtualNetwork newVnet = vnetAdminService.createVirtualNetwork(tid);
123 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
124 .path("vnets")
125 .path(newVnet.id().toString());
126 return Response
127 .created(locationBuilder.build())
128 .build();
129 } catch (IOException e) {
130 throw new IllegalArgumentException(e);
131 }
132 }
133
134 /**
135 * Removes the virtual network with the specified network identifier.
136 *
137 * @param networkId network identifier
Jian Lic2a542b2016-05-10 11:48:19 -0700138 * @return 204 NO CONTENT
Claudine Chiufb8b8162016-04-01 23:50:51 +0000139 */
140 @DELETE
141 @Path("{networkId}")
142 public Response removeVirtualNetwork(@PathParam("networkId") long networkId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000143 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000144 vnetAdminService.removeVirtualNetwork(nid);
Jian Lic2a542b2016-05-10 11:48:19 -0700145 return Response.noContent().build();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000146 }
147
148 // VirtualDevice
149
150 /**
151 * Returns all virtual network devices in a virtual network.
152 *
153 * @param networkId network identifier
154 * @return 200 OK
Claudine Chiu1decd532016-04-19 18:30:01 +0000155 * @onos.rsModel VirtualDevices
Claudine Chiufb8b8162016-04-01 23:50:51 +0000156 */
157 @GET
158 @Produces(MediaType.APPLICATION_JSON)
159 @Path("{networkId}/devices")
160 public Response getVirtualDevices(@PathParam("networkId") long networkId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000161 NetworkId nid = NetworkId.networkId(networkId);
Brian Stanke9a108972016-04-11 15:25:17 -0400162 Set<VirtualDevice> vdevs = vnetService.getVirtualDevices(nid);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000163 return ok(encodeArray(VirtualDevice.class, "devices", vdevs)).build();
164 }
165
166 /**
167 * Creates a virtual device from the JSON input stream.
168 *
169 * @param networkId network identifier
Claudine Chiu1decd532016-04-19 18:30:01 +0000170 * @param stream virtual device JSON stream
Claudine Chiufb8b8162016-04-01 23:50:51 +0000171 * @return status of the request - CREATED if the JSON is correct,
172 * BAD_REQUEST if the JSON is invalid
173 * @onos.rsModel VirtualDevice
174 */
175 @POST
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000176 @Path("{networkId}/devices")
Claudine Chiufb8b8162016-04-01 23:50:51 +0000177 @Consumes(MediaType.APPLICATION_JSON)
178 @Produces(MediaType.APPLICATION_JSON)
179 public Response createVirtualDevice(@PathParam("networkId") long networkId,
180 InputStream stream) {
181 try {
182 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
183 final VirtualDevice vdevReq = codec(VirtualDevice.class).decode(jsonTree, this);
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000184 JsonNode specifiedNetworkId = jsonTree.get("networkId");
185 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000186 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
187 }
188 final VirtualDevice vdevRes = vnetAdminService.createVirtualDevice(vdevReq.networkId(),
189 vdevReq.id());
190 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000191 .path("vnets").path(specifiedNetworkId.asText())
Claudine Chiufb8b8162016-04-01 23:50:51 +0000192 .path("devices").path(vdevRes.id().toString());
193 return Response
194 .created(locationBuilder.build())
195 .build();
196 } catch (IOException e) {
197 throw new IllegalArgumentException(e);
198 }
199 }
200
201 /**
202 * Removes the virtual network device from the virtual network.
203 *
204 * @param networkId network identifier
Brian Stanke9a108972016-04-11 15:25:17 -0400205 * @param deviceId device identifier
Jian Lic2a542b2016-05-10 11:48:19 -0700206 * @return 204 NO CONTENT
Claudine Chiufb8b8162016-04-01 23:50:51 +0000207 */
208 @DELETE
209 @Path("{networkId}/devices/{deviceId}")
210 public Response removeVirtualDevice(@PathParam("networkId") long networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400211 @PathParam("deviceId") String deviceId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000212 NetworkId nid = NetworkId.networkId(networkId);
213 DeviceId did = DeviceId.deviceId(deviceId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000214 vnetAdminService.removeVirtualDevice(nid, did);
Jian Lic2a542b2016-05-10 11:48:19 -0700215 return Response.noContent().build();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000216 }
217
218 // VirtualPort
219
220 /**
221 * Returns all virtual network ports in a virtual device in a virtual network.
222 *
223 * @param networkId network identifier
Brian Stanke9a108972016-04-11 15:25:17 -0400224 * @param deviceId virtual device identifier
Claudine Chiufb8b8162016-04-01 23:50:51 +0000225 * @return 200 OK
Claudine Chiu1decd532016-04-19 18:30:01 +0000226 * @onos.rsModel VirtualPorts
Claudine Chiufb8b8162016-04-01 23:50:51 +0000227 */
228 @GET
229 @Produces(MediaType.APPLICATION_JSON)
230 @Path("{networkId}/devices/{deviceId}/ports")
231 public Response getVirtualPorts(@PathParam("networkId") long networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400232 @PathParam("deviceId") String deviceId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000233 NetworkId nid = NetworkId.networkId(networkId);
Brian Stanke9a108972016-04-11 15:25:17 -0400234 Iterable<VirtualPort> vports = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000235 return ok(encodeArray(VirtualPort.class, "ports", vports)).build();
236 }
237
238 /**
239 * Creates a virtual network port in a virtual device in a virtual network.
240 *
Brian Stanke9a108972016-04-11 15:25:17 -0400241 * @param networkId network identifier
Claudine Chiufb8b8162016-04-01 23:50:51 +0000242 * @param virtDeviceId virtual device identifier
Claudine Chiu1decd532016-04-19 18:30:01 +0000243 * @param stream virtual port JSON stream
Claudine Chiufb8b8162016-04-01 23:50:51 +0000244 * @return status of the request - CREATED if the JSON is correct,
245 * BAD_REQUEST if the JSON is invalid
246 * @onos.rsModel VirtualPort
247 */
248 @POST
249 @Consumes(MediaType.APPLICATION_JSON)
250 @Produces(MediaType.APPLICATION_JSON)
251 @Path("{networkId}/devices/{deviceId}/ports")
252 public Response createVirtualPort(@PathParam("networkId") long networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400253 @PathParam("deviceId") String virtDeviceId,
254 InputStream stream) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000255 try {
256 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
257// final VirtualPort vportReq = codec(VirtualPort.class).decode(jsonTree, this);
258 JsonNode specifiedNetworkId = jsonTree.get("networkId");
259 JsonNode specifiedDeviceId = jsonTree.get("deviceId");
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000260 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000261 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
262 }
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000263 if (specifiedDeviceId == null || !specifiedDeviceId.asText().equals(virtDeviceId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000264 throw new IllegalArgumentException(INVALID_FIELD + "deviceId");
265 }
266 JsonNode specifiedPortNum = jsonTree.get("portNum");
267 JsonNode specifiedPhysDeviceId = jsonTree.get("physDeviceId");
268 JsonNode specifiedPhysPortNum = jsonTree.get("physPortNum");
269 final NetworkId nid = NetworkId.networkId(networkId);
270 DeviceId vdevId = DeviceId.deviceId(virtDeviceId);
271 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
272 Device physDevice = new DefaultDevice(null, DeviceId.deviceId(specifiedPhysDeviceId.asText()),
Brian Stanke9a108972016-04-11 15:25:17 -0400273 null, null, null, null, null, null, annotations);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000274 Port realizedBy = new DefaultPort(physDevice,
Brian Stanke9a108972016-04-11 15:25:17 -0400275 PortNumber.portNumber(specifiedPhysPortNum.asText()), true);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000276 VirtualPort vport = vnetAdminService.createVirtualPort(nid, vdevId,
Brian Stanke9a108972016-04-11 15:25:17 -0400277 PortNumber.portNumber(specifiedPortNum.asText()), realizedBy);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000278 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
279 .path("vnets").path(specifiedNetworkId.asText())
280 .path("devices").path(specifiedDeviceId.asText())
281 .path("ports").path(vport.number().toString());
282 return Response
283 .created(locationBuilder.build())
284 .build();
285 } catch (IOException e) {
286 throw new IllegalArgumentException(e);
287 }
288 }
289
290 /**
291 * Removes the virtual network port from the virtual device in a virtual network.
292 *
293 * @param networkId network identifier
Brian Stanke9a108972016-04-11 15:25:17 -0400294 * @param deviceId virtual device identifier
295 * @param portNum virtual port number
Jian Lic2a542b2016-05-10 11:48:19 -0700296 * @return 204 NO CONTENT
Claudine Chiufb8b8162016-04-01 23:50:51 +0000297 */
298 @DELETE
299 @Path("{networkId}/devices/{deviceId}/ports/{portNum}")
300 public Response removeVirtualPort(@PathParam("networkId") long networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400301 @PathParam("deviceId") String deviceId,
302 @PathParam("portNum") long portNum) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000303 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000304 vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId),
Brian Stanke9a108972016-04-11 15:25:17 -0400305 PortNumber.portNumber(portNum));
Jian Lic2a542b2016-05-10 11:48:19 -0700306 return Response.noContent().build();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000307 }
308
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000309 // VirtualLink
310
311 /**
312 * Returns all virtual network links in a virtual network.
313 *
314 * @param networkId network identifier
315 * @return 200 OK
Claudine Chiu1decd532016-04-19 18:30:01 +0000316 * @onos.rsModel VirtualLinks
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000317 */
318 @GET
319 @Produces(MediaType.APPLICATION_JSON)
320 @Path("{networkId}/links")
321 public Response getVirtualLinks(@PathParam("networkId") long networkId) {
322 NetworkId nid = NetworkId.networkId(networkId);
Brian Stanke9a108972016-04-11 15:25:17 -0400323 Set<VirtualLink> vlinks = vnetService.getVirtualLinks(nid);
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000324 return ok(encodeArray(VirtualLink.class, "links", vlinks)).build();
325 }
326
Brian Stanke9a108972016-04-11 15:25:17 -0400327 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000328 * Creates a virtual network link from the JSON input stream.
329 *
330 * @param networkId network identifier
Claudine Chiu1decd532016-04-19 18:30:01 +0000331 * @param stream virtual link JSON stream
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000332 * @return status of the request - CREATED if the JSON is correct,
333 * BAD_REQUEST if the JSON is invalid
334 * @onos.rsModel VirtualLink
335 */
336 @POST
337 @Path("{networkId}/links")
338 @Consumes(MediaType.APPLICATION_JSON)
339 @Produces(MediaType.APPLICATION_JSON)
340 public Response createVirtualLink(@PathParam("networkId") long networkId,
341 InputStream stream) {
342 try {
343 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
344 JsonNode specifiedNetworkId = jsonTree.get("networkId");
345 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
346 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
347 }
348 final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000349 vnetAdminService.createVirtualLink(vlinkReq.networkId(),
Brian Stanke9a108972016-04-11 15:25:17 -0400350 vlinkReq.src(), vlinkReq.dst());
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000351 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
352 .path("vnets").path(specifiedNetworkId.asText())
353 .path("links");
354 return Response
355 .created(locationBuilder.build())
356 .build();
357 } catch (IOException e) {
358 throw new IllegalArgumentException(e);
359 }
360 }
361
362 /**
363 * Removes the virtual network link from the JSON input stream.
364 *
365 * @param networkId network identifier
Claudine Chiu1decd532016-04-19 18:30:01 +0000366 * @param stream virtual link JSON stream
Jian Lic2a542b2016-05-10 11:48:19 -0700367 * @return 204 NO CONTENT
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000368 * @onos.rsModel VirtualLink
369 */
370 @DELETE
371 @Path("{networkId}/links")
372 @Consumes(MediaType.APPLICATION_JSON)
373 public Response removeVirtualLink(@PathParam("networkId") long networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400374 InputStream stream) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000375 try {
376 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
377 JsonNode specifiedNetworkId = jsonTree.get("networkId");
378 if (specifiedNetworkId != null &&
379 specifiedNetworkId.asLong() != (networkId)) {
380 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
381 }
382 final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
383 vnetAdminService.removeVirtualLink(vlinkReq.networkId(),
Brian Stanke9a108972016-04-11 15:25:17 -0400384 vlinkReq.src(), vlinkReq.dst());
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000385 } catch (IOException e) {
386 throw new IllegalArgumentException(e);
387 }
388
Jian Lic2a542b2016-05-10 11:48:19 -0700389 return Response.noContent().build();
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000390 }
391
392 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000393 * Get the tenant identifier from the JSON stream.
394 *
Brian Stanke9a108972016-04-11 15:25:17 -0400395 * @param stream TenantId JSON stream
Claudine Chiufb8b8162016-04-01 23:50:51 +0000396 * @param jsonFieldName field name
397 * @return JsonNode
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000398 * @throws IOException if unable to parse the request
Claudine Chiufb8b8162016-04-01 23:50:51 +0000399 */
400 private JsonNode getFromJsonStream(InputStream stream, String jsonFieldName) throws IOException {
401 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
402 JsonNode jsonNode = jsonTree.get(jsonFieldName);
403
404 if (jsonNode == null) {
405 throw new IllegalArgumentException(MISSING_FIELD + jsonFieldName);
406 }
407 return jsonNode;
408 }
409}