blob: 8df87223f5ddcb5125b190c0a07cca70f3174891 [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;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000021import org.onosproject.incubator.net.tunnel.TunnelId;
22import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000023import org.onosproject.incubator.net.virtual.NetworkId;
24import org.onosproject.incubator.net.virtual.TenantId;
25import org.onosproject.incubator.net.virtual.VirtualDevice;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000026import org.onosproject.incubator.net.virtual.VirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000027import org.onosproject.incubator.net.virtual.VirtualNetwork;
28import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
29import org.onosproject.incubator.net.virtual.VirtualNetworkService;
30import org.onosproject.incubator.net.virtual.VirtualPort;
31import org.onosproject.net.DefaultAnnotations;
32import org.onosproject.net.DefaultDevice;
33import org.onosproject.net.DefaultPort;
34import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.Port;
37import org.onosproject.net.PortNumber;
38import org.onosproject.rest.AbstractWebResource;
39
40import javax.ws.rs.Consumes;
41import javax.ws.rs.DELETE;
42import javax.ws.rs.GET;
43import javax.ws.rs.POST;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000044import javax.ws.rs.PUT;
Claudine Chiufb8b8162016-04-01 23:50:51 +000045import javax.ws.rs.Path;
46import javax.ws.rs.PathParam;
47import javax.ws.rs.Produces;
48import javax.ws.rs.core.Context;
49import javax.ws.rs.core.MediaType;
50import javax.ws.rs.core.Response;
51import javax.ws.rs.core.UriBuilder;
52import javax.ws.rs.core.UriInfo;
53import java.io.IOException;
54import java.io.InputStream;
55import java.util.Collection;
56import java.util.List;
57import java.util.Set;
58import java.util.stream.Collectors;
59
60/**
61 * Query and Manage Virtual Network elements.
62 */
63@Path("vnets")
64public class VirtualNetworkWebResource extends AbstractWebResource {
65
66 private static final String MISSING_FIELD = "Missing ";
67 private static final String INVALID_FIELD = "Invalid ";
68
69 private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class);
70 private final VirtualNetworkService vnetService = get(VirtualNetworkService.class);
71
72 @Context
73 UriInfo uriInfo;
74
75 // VirtualNetwork
Claudine Chiufb8b8162016-04-01 23:50:51 +000076
77 /**
78 * Returns all virtual networks.
79 *
80 * @return 200 OK
81 */
82 @GET
83 @Produces(MediaType.APPLICATION_JSON)
84 public Response getVirtualNetworks() {
85 Set<TenantId> tenantIds = vnetAdminService.getTenantIds();
86 List<VirtualNetwork> allVnets = tenantIds.stream()
87 .map(tenantId -> vnetService.getVirtualNetworks(tenantId))
88 .flatMap(Collection::stream)
89 .collect(Collectors.toList());
90 return ok(encodeArray(VirtualNetwork.class, "vnets", allVnets)).build();
91 }
92
93 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000094 * Returns the virtual networks with the specified tenant identifier.
95 *
96 * @param tenantId tenant identifier
97 * @return 200 OK, 404 not found
98 */
99 @GET
100 @Produces(MediaType.APPLICATION_JSON)
101 @Path("{tenantId}")
102 public Response getVirtualNetworkById(@PathParam("tenantId") String tenantId) {
103 final TenantId existingTid = TenantWebResource.getExistingTenantId(vnetAdminService,
104 TenantId.tenantId(tenantId));
105 Set<VirtualNetwork> vnets = vnetService.getVirtualNetworks(existingTid);
106 return ok(encodeArray(VirtualNetwork.class, "vnets", vnets)).build();
107 }
108
109 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000110 * Creates a virtual network from the JSON input stream.
111 *
112 * @param stream TenantId JSON stream
113 * @return status of the request - CREATED if the JSON is correct,
114 * BAD_REQUEST if the JSON is invalid
115 * @onos.rsModel TenantId
116 */
117 @POST
118 @Consumes(MediaType.APPLICATION_JSON)
119 @Produces(MediaType.APPLICATION_JSON)
120 public Response createVirtualNetwork(InputStream stream) {
121 try {
122 final TenantId tid = TenantId.tenantId(getFromJsonStream(stream, "id").asText());
123 VirtualNetwork newVnet = vnetAdminService.createVirtualNetwork(tid);
124 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
125 .path("vnets")
126 .path(newVnet.id().toString());
127 return Response
128 .created(locationBuilder.build())
129 .build();
130 } catch (IOException e) {
131 throw new IllegalArgumentException(e);
132 }
133 }
134
135 /**
136 * Removes the virtual network with the specified network identifier.
137 *
138 * @param networkId network identifier
139 * @return 200 OK, 404 not found
140 */
141 @DELETE
142 @Path("{networkId}")
143 public Response removeVirtualNetwork(@PathParam("networkId") long networkId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000144 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000145 vnetAdminService.removeVirtualNetwork(nid);
146 return Response.ok().build();
147 }
148
149 // VirtualDevice
150
151 /**
152 * Returns all virtual network devices in a virtual network.
153 *
154 * @param networkId network identifier
155 * @return 200 OK
156 */
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);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000162 Set<VirtualDevice> vdevs = vnetService.getVirtualDevices(nid);
163 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
170 * @param stream Virtual device JSON stream
171 * @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
205 * @param deviceId device identifier
206 * @return 200 OK, 404 not found
207 */
208 @DELETE
209 @Path("{networkId}/devices/{deviceId}")
210 public Response removeVirtualDevice(@PathParam("networkId") long networkId,
211 @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);
215 return Response.ok().build();
216 }
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
224 * @param deviceId virtual device identifier
225 * @return 200 OK
226 */
227 @GET
228 @Produces(MediaType.APPLICATION_JSON)
229 @Path("{networkId}/devices/{deviceId}/ports")
230 public Response getVirtualPorts(@PathParam("networkId") long networkId,
231 @PathParam("deviceId") String deviceId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000232 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000233 Iterable<VirtualPort> vports = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
234 return ok(encodeArray(VirtualPort.class, "ports", vports)).build();
235 }
236
237 /**
238 * Creates a virtual network port in a virtual device in a virtual network.
239 *
240 * @param networkId network identifier
241 * @param virtDeviceId virtual device identifier
242 * @param stream Virtual device JSON stream
243 * @return status of the request - CREATED if the JSON is correct,
244 * BAD_REQUEST if the JSON is invalid
245 * @onos.rsModel VirtualPort
246 */
247 @POST
248 @Consumes(MediaType.APPLICATION_JSON)
249 @Produces(MediaType.APPLICATION_JSON)
250 @Path("{networkId}/devices/{deviceId}/ports")
251 public Response createVirtualPort(@PathParam("networkId") long networkId,
252 @PathParam("deviceId") String virtDeviceId,
253 InputStream stream) {
254 try {
255 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
256// final VirtualPort vportReq = codec(VirtualPort.class).decode(jsonTree, this);
257 JsonNode specifiedNetworkId = jsonTree.get("networkId");
258 JsonNode specifiedDeviceId = jsonTree.get("deviceId");
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000259 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000260 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
261 }
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000262 if (specifiedDeviceId == null || !specifiedDeviceId.asText().equals(virtDeviceId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000263 throw new IllegalArgumentException(INVALID_FIELD + "deviceId");
264 }
265 JsonNode specifiedPortNum = jsonTree.get("portNum");
266 JsonNode specifiedPhysDeviceId = jsonTree.get("physDeviceId");
267 JsonNode specifiedPhysPortNum = jsonTree.get("physPortNum");
268 final NetworkId nid = NetworkId.networkId(networkId);
269 DeviceId vdevId = DeviceId.deviceId(virtDeviceId);
270 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
271 Device physDevice = new DefaultDevice(null, DeviceId.deviceId(specifiedPhysDeviceId.asText()),
272 null, null, null, null, null, null, annotations);
273 Port realizedBy = new DefaultPort(physDevice,
274 PortNumber.portNumber(specifiedPhysPortNum.asText()), true);
275 VirtualPort vport = vnetAdminService.createVirtualPort(nid, vdevId,
276 PortNumber.portNumber(specifiedPortNum.asText()), realizedBy);
277 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
278 .path("vnets").path(specifiedNetworkId.asText())
279 .path("devices").path(specifiedDeviceId.asText())
280 .path("ports").path(vport.number().toString());
281 return Response
282 .created(locationBuilder.build())
283 .build();
284 } catch (IOException e) {
285 throw new IllegalArgumentException(e);
286 }
287 }
288
289 /**
290 * Removes the virtual network port from the virtual device in a virtual network.
291 *
292 * @param networkId network identifier
293 * @param deviceId virtual device identifier
294 * @param portNum virtual port number
295 * @return 200 OK, 404 not found
296 */
297 @DELETE
298 @Path("{networkId}/devices/{deviceId}/ports/{portNum}")
299 public Response removeVirtualPort(@PathParam("networkId") long networkId,
300 @PathParam("deviceId") String deviceId,
301 @PathParam("portNum") long portNum) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000302 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000303 vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId),
304 PortNumber.portNumber(portNum));
305 return Response.ok().build();
306 }
307
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000308 // VirtualLink
309
310 /**
311 * Returns all virtual network links in a virtual network.
312 *
313 * @param networkId network identifier
314 * @return 200 OK
315 */
316 @GET
317 @Produces(MediaType.APPLICATION_JSON)
318 @Path("{networkId}/links")
319 public Response getVirtualLinks(@PathParam("networkId") long networkId) {
320 NetworkId nid = NetworkId.networkId(networkId);
321 Set<VirtualLink> vlinks = vnetService.getVirtualLinks(nid);
322 return ok(encodeArray(VirtualLink.class, "links", vlinks)).build();
323 }
324
325 /**
326 * Creates a virtual network link from the JSON input stream.
327 *
328 * @param networkId network identifier
329 * @param stream Virtual device JSON stream
330 * @return status of the request - CREATED if the JSON is correct,
331 * BAD_REQUEST if the JSON is invalid
332 * @onos.rsModel VirtualLink
333 */
334 @POST
335 @Path("{networkId}/links")
336 @Consumes(MediaType.APPLICATION_JSON)
337 @Produces(MediaType.APPLICATION_JSON)
338 public Response createVirtualLink(@PathParam("networkId") long networkId,
339 InputStream stream) {
340 try {
341 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
342 JsonNode specifiedNetworkId = jsonTree.get("networkId");
343 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
344 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
345 }
346 final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
347 TunnelId tunnelId = TunnelId.valueOf(0);
348 if (vlinkReq instanceof DefaultVirtualLink) {
349 tunnelId = ((DefaultVirtualLink) vlinkReq).tunnelId();
350 }
351 vnetAdminService.createVirtualLink(vlinkReq.networkId(),
352 vlinkReq.src(), vlinkReq.dst(), tunnelId);
353 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
354 .path("vnets").path(specifiedNetworkId.asText())
355 .path("links");
356 return Response
357 .created(locationBuilder.build())
358 .build();
359 } catch (IOException e) {
360 throw new IllegalArgumentException(e);
361 }
362 }
363
364 /**
365 * Removes the virtual network link from the JSON input stream.
366 *
367 * @param networkId network identifier
368 * @param stream deviceIds JSON stream
369 * @return 200 OK, 404 not found
370 * @onos.rsModel VirtualLink
371 */
372 @DELETE
373 @Path("{networkId}/links")
374 @Consumes(MediaType.APPLICATION_JSON)
375 public Response removeVirtualLink(@PathParam("networkId") long networkId,
376 InputStream stream) {
377 try {
378 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
379 JsonNode specifiedNetworkId = jsonTree.get("networkId");
380 if (specifiedNetworkId != null &&
381 specifiedNetworkId.asLong() != (networkId)) {
382 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
383 }
384 final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
385 vnetAdminService.removeVirtualLink(vlinkReq.networkId(),
386 vlinkReq.src(), vlinkReq.dst());
387 } catch (IOException e) {
388 throw new IllegalArgumentException(e);
389 }
390
391 return Response.ok().build();
392 }
393
394 /**
395 * Removes the virtual network link from the JSON input stream.
396 *
397 * @param networkId network identifier
398 * @param stream deviceIds JSON stream
399 * @return 200 OK, 404 not found
400 * @onos.rsModel VirtualLink
401 */
402
403 @PUT
404 @Path("{networkId}/links/remove")
405 @Consumes(MediaType.APPLICATION_JSON)
406 @Produces(MediaType.APPLICATION_JSON)
407 public Response removeVirtualLink2(@PathParam("networkId") long networkId,
408 InputStream stream) {
409 try {
410 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
411 JsonNode specifiedNetworkId = jsonTree.get("networkId");
412 if (specifiedNetworkId != null &&
413 specifiedNetworkId.asLong() != (networkId)) {
414 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
415 }
416 final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
417 vnetAdminService.removeVirtualLink(vlinkReq.networkId(),
418 vlinkReq.src(), vlinkReq.dst());
419 } catch (IOException e) {
420 throw new IllegalArgumentException(e);
421 }
422
423 return Response.ok().build();
424 }
Claudine Chiufb8b8162016-04-01 23:50:51 +0000425
426 /**
427 * Get the tenant identifier from the JSON stream.
428 *
429 * @param stream TenantId JSON stream
430 * @param jsonFieldName field name
431 * @return JsonNode
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000432 * @throws IOException if unable to parse the request
Claudine Chiufb8b8162016-04-01 23:50:51 +0000433 */
434 private JsonNode getFromJsonStream(InputStream stream, String jsonFieldName) throws IOException {
435 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
436 JsonNode jsonNode = jsonTree.get(jsonFieldName);
437
438 if (jsonNode == null) {
439 throw new IllegalArgumentException(MISSING_FIELD + jsonFieldName);
440 }
441 return jsonNode;
442 }
443}