blob: d17610241c0d835499c326f045f6f09a91b5870e [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;
44import javax.ws.rs.Path;
45import javax.ws.rs.PathParam;
46import javax.ws.rs.Produces;
47import javax.ws.rs.core.Context;
48import javax.ws.rs.core.MediaType;
49import javax.ws.rs.core.Response;
50import javax.ws.rs.core.UriBuilder;
51import javax.ws.rs.core.UriInfo;
52import java.io.IOException;
53import java.io.InputStream;
54import java.util.Collection;
55import java.util.List;
56import java.util.Set;
57import java.util.stream.Collectors;
58
59/**
60 * Query and Manage Virtual Network elements.
61 */
62@Path("vnets")
63public class VirtualNetworkWebResource extends AbstractWebResource {
64
65 private static final String MISSING_FIELD = "Missing ";
66 private static final String INVALID_FIELD = "Invalid ";
67
68 private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class);
69 private final VirtualNetworkService vnetService = get(VirtualNetworkService.class);
70
71 @Context
72 UriInfo uriInfo;
73
74 // VirtualNetwork
Claudine Chiufb8b8162016-04-01 23:50:51 +000075
76 /**
77 * Returns all virtual networks.
78 *
79 * @return 200 OK
80 */
81 @GET
82 @Produces(MediaType.APPLICATION_JSON)
83 public Response getVirtualNetworks() {
84 Set<TenantId> tenantIds = vnetAdminService.getTenantIds();
85 List<VirtualNetwork> allVnets = tenantIds.stream()
86 .map(tenantId -> vnetService.getVirtualNetworks(tenantId))
87 .flatMap(Collection::stream)
88 .collect(Collectors.toList());
89 return ok(encodeArray(VirtualNetwork.class, "vnets", allVnets)).build();
90 }
91
92 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000093 * Returns the virtual networks with the specified tenant identifier.
94 *
95 * @param tenantId tenant identifier
96 * @return 200 OK, 404 not found
97 */
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,
103 TenantId.tenantId(tenantId));
104 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 *
111 * @param stream TenantId JSON stream
112 * @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
138 * @return 200 OK, 404 not found
139 */
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);
145 return Response.ok().build();
146 }
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
155 */
156 @GET
157 @Produces(MediaType.APPLICATION_JSON)
158 @Path("{networkId}/devices")
159 public Response getVirtualDevices(@PathParam("networkId") long networkId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000160 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000161 Set<VirtualDevice> vdevs = vnetService.getVirtualDevices(nid);
162 return ok(encodeArray(VirtualDevice.class, "devices", vdevs)).build();
163 }
164
165 /**
166 * Creates a virtual device from the JSON input stream.
167 *
168 * @param networkId network identifier
169 * @param stream Virtual device JSON stream
170 * @return status of the request - CREATED if the JSON is correct,
171 * BAD_REQUEST if the JSON is invalid
172 * @onos.rsModel VirtualDevice
173 */
174 @POST
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000175 @Path("{networkId}/devices")
Claudine Chiufb8b8162016-04-01 23:50:51 +0000176 @Consumes(MediaType.APPLICATION_JSON)
177 @Produces(MediaType.APPLICATION_JSON)
178 public Response createVirtualDevice(@PathParam("networkId") long networkId,
179 InputStream stream) {
180 try {
181 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
182 final VirtualDevice vdevReq = codec(VirtualDevice.class).decode(jsonTree, this);
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000183 JsonNode specifiedNetworkId = jsonTree.get("networkId");
184 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000185 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
186 }
187 final VirtualDevice vdevRes = vnetAdminService.createVirtualDevice(vdevReq.networkId(),
188 vdevReq.id());
189 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000190 .path("vnets").path(specifiedNetworkId.asText())
Claudine Chiufb8b8162016-04-01 23:50:51 +0000191 .path("devices").path(vdevRes.id().toString());
192 return Response
193 .created(locationBuilder.build())
194 .build();
195 } catch (IOException e) {
196 throw new IllegalArgumentException(e);
197 }
198 }
199
200 /**
201 * Removes the virtual network device from the virtual network.
202 *
203 * @param networkId network identifier
204 * @param deviceId device identifier
205 * @return 200 OK, 404 not found
206 */
207 @DELETE
208 @Path("{networkId}/devices/{deviceId}")
209 public Response removeVirtualDevice(@PathParam("networkId") long networkId,
210 @PathParam("deviceId") String deviceId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000211 NetworkId nid = NetworkId.networkId(networkId);
212 DeviceId did = DeviceId.deviceId(deviceId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000213 vnetAdminService.removeVirtualDevice(nid, did);
214 return Response.ok().build();
215 }
216
217 // VirtualPort
218
219 /**
220 * Returns all virtual network ports in a virtual device in a virtual network.
221 *
222 * @param networkId network identifier
223 * @param deviceId virtual device identifier
224 * @return 200 OK
225 */
226 @GET
227 @Produces(MediaType.APPLICATION_JSON)
228 @Path("{networkId}/devices/{deviceId}/ports")
229 public Response getVirtualPorts(@PathParam("networkId") long networkId,
230 @PathParam("deviceId") String deviceId) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000231 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000232 Iterable<VirtualPort> vports = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
233 return ok(encodeArray(VirtualPort.class, "ports", vports)).build();
234 }
235
236 /**
237 * Creates a virtual network port in a virtual device in a virtual network.
238 *
239 * @param networkId network identifier
240 * @param virtDeviceId virtual device identifier
241 * @param stream Virtual device JSON stream
242 * @return status of the request - CREATED if the JSON is correct,
243 * BAD_REQUEST if the JSON is invalid
244 * @onos.rsModel VirtualPort
245 */
246 @POST
247 @Consumes(MediaType.APPLICATION_JSON)
248 @Produces(MediaType.APPLICATION_JSON)
249 @Path("{networkId}/devices/{deviceId}/ports")
250 public Response createVirtualPort(@PathParam("networkId") long networkId,
251 @PathParam("deviceId") String virtDeviceId,
252 InputStream stream) {
253 try {
254 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
255// final VirtualPort vportReq = codec(VirtualPort.class).decode(jsonTree, this);
256 JsonNode specifiedNetworkId = jsonTree.get("networkId");
257 JsonNode specifiedDeviceId = jsonTree.get("deviceId");
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000258 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000259 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
260 }
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000261 if (specifiedDeviceId == null || !specifiedDeviceId.asText().equals(virtDeviceId)) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000262 throw new IllegalArgumentException(INVALID_FIELD + "deviceId");
263 }
264 JsonNode specifiedPortNum = jsonTree.get("portNum");
265 JsonNode specifiedPhysDeviceId = jsonTree.get("physDeviceId");
266 JsonNode specifiedPhysPortNum = jsonTree.get("physPortNum");
267 final NetworkId nid = NetworkId.networkId(networkId);
268 DeviceId vdevId = DeviceId.deviceId(virtDeviceId);
269 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
270 Device physDevice = new DefaultDevice(null, DeviceId.deviceId(specifiedPhysDeviceId.asText()),
271 null, null, null, null, null, null, annotations);
272 Port realizedBy = new DefaultPort(physDevice,
273 PortNumber.portNumber(specifiedPhysPortNum.asText()), true);
274 VirtualPort vport = vnetAdminService.createVirtualPort(nid, vdevId,
275 PortNumber.portNumber(specifiedPortNum.asText()), realizedBy);
276 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
277 .path("vnets").path(specifiedNetworkId.asText())
278 .path("devices").path(specifiedDeviceId.asText())
279 .path("ports").path(vport.number().toString());
280 return Response
281 .created(locationBuilder.build())
282 .build();
283 } catch (IOException e) {
284 throw new IllegalArgumentException(e);
285 }
286 }
287
288 /**
289 * Removes the virtual network port from the virtual device in a virtual network.
290 *
291 * @param networkId network identifier
292 * @param deviceId virtual device identifier
293 * @param portNum virtual port number
294 * @return 200 OK, 404 not found
295 */
296 @DELETE
297 @Path("{networkId}/devices/{deviceId}/ports/{portNum}")
298 public Response removeVirtualPort(@PathParam("networkId") long networkId,
299 @PathParam("deviceId") String deviceId,
300 @PathParam("portNum") long portNum) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000301 NetworkId nid = NetworkId.networkId(networkId);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000302 vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId),
303 PortNumber.portNumber(portNum));
304 return Response.ok().build();
305 }
306
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000307 // VirtualLink
308
309 /**
310 * Returns all virtual network links in a virtual network.
311 *
312 * @param networkId network identifier
313 * @return 200 OK
314 */
315 @GET
316 @Produces(MediaType.APPLICATION_JSON)
317 @Path("{networkId}/links")
318 public Response getVirtualLinks(@PathParam("networkId") long networkId) {
319 NetworkId nid = NetworkId.networkId(networkId);
320 Set<VirtualLink> vlinks = vnetService.getVirtualLinks(nid);
321 return ok(encodeArray(VirtualLink.class, "links", vlinks)).build();
322 }
323
324 /**
325 * Creates a virtual network link from the JSON input stream.
326 *
327 * @param networkId network identifier
328 * @param stream Virtual device JSON stream
329 * @return status of the request - CREATED if the JSON is correct,
330 * BAD_REQUEST if the JSON is invalid
331 * @onos.rsModel VirtualLink
332 */
333 @POST
334 @Path("{networkId}/links")
335 @Consumes(MediaType.APPLICATION_JSON)
336 @Produces(MediaType.APPLICATION_JSON)
337 public Response createVirtualLink(@PathParam("networkId") long networkId,
338 InputStream stream) {
339 try {
340 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
341 JsonNode specifiedNetworkId = jsonTree.get("networkId");
342 if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
343 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
344 }
345 final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
346 TunnelId tunnelId = TunnelId.valueOf(0);
347 if (vlinkReq instanceof DefaultVirtualLink) {
348 tunnelId = ((DefaultVirtualLink) vlinkReq).tunnelId();
349 }
350 vnetAdminService.createVirtualLink(vlinkReq.networkId(),
351 vlinkReq.src(), vlinkReq.dst(), tunnelId);
352 UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
353 .path("vnets").path(specifiedNetworkId.asText())
354 .path("links");
355 return Response
356 .created(locationBuilder.build())
357 .build();
358 } catch (IOException e) {
359 throw new IllegalArgumentException(e);
360 }
361 }
362
363 /**
364 * Removes the virtual network link from the JSON input stream.
365 *
366 * @param networkId network identifier
367 * @param stream deviceIds JSON stream
368 * @return 200 OK, 404 not found
369 * @onos.rsModel VirtualLink
370 */
371 @DELETE
372 @Path("{networkId}/links")
373 @Consumes(MediaType.APPLICATION_JSON)
374 public Response removeVirtualLink(@PathParam("networkId") long networkId,
375 InputStream stream) {
376 try {
377 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
378 JsonNode specifiedNetworkId = jsonTree.get("networkId");
379 if (specifiedNetworkId != null &&
380 specifiedNetworkId.asLong() != (networkId)) {
381 throw new IllegalArgumentException(INVALID_FIELD + "networkId");
382 }
383 final VirtualLink vlinkReq = codec(VirtualLink.class).decode(jsonTree, this);
384 vnetAdminService.removeVirtualLink(vlinkReq.networkId(),
385 vlinkReq.src(), vlinkReq.dst());
386 } catch (IOException e) {
387 throw new IllegalArgumentException(e);
388 }
389
390 return Response.ok().build();
391 }
392
393 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000394 * Get the tenant identifier from the JSON stream.
395 *
396 * @param stream TenantId JSON stream
397 * @param jsonFieldName field name
398 * @return JsonNode
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000399 * @throws IOException if unable to parse the request
Claudine Chiufb8b8162016-04-01 23:50:51 +0000400 */
401 private JsonNode getFromJsonStream(InputStream stream, String jsonFieldName) throws IOException {
402 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
403 JsonNode jsonNode = jsonTree.get(jsonFieldName);
404
405 if (jsonNode == null) {
406 throw new IllegalArgumentException(MISSING_FIELD + jsonFieldName);
407 }
408 return jsonNode;
409 }
410}