blob: 56a4755ca5a7c983050d03c28af1db7b3fcfa1ae [file] [log] [blame]
Jian Lie9ac2c52016-01-13 17:42:05 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jian Lie9ac2c52016-01-13 17:42:05 -08003 *
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 */
16package org.onosproject.rest.resources;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import org.onosproject.net.DeviceId;
21import org.onosproject.net.flowobjective.FilteringObjective;
22import org.onosproject.net.flowobjective.FlowObjectiveService;
23import org.onosproject.net.flowobjective.ForwardingObjective;
24import org.onosproject.net.flowobjective.NextObjective;
25import org.onosproject.rest.AbstractWebResource;
26
27import javax.ws.rs.Consumes;
28import javax.ws.rs.GET;
29import javax.ws.rs.POST;
30import javax.ws.rs.Path;
31import javax.ws.rs.PathParam;
32import javax.ws.rs.Produces;
Jian Lia424a052016-05-30 21:02:33 +090033import javax.ws.rs.QueryParam;
Jian Li9d616492016-03-09 10:52:49 -080034import javax.ws.rs.core.Context;
Jian Lie9ac2c52016-01-13 17:42:05 -080035import javax.ws.rs.core.MediaType;
36import javax.ws.rs.core.Response;
Jian Li9d616492016-03-09 10:52:49 -080037import javax.ws.rs.core.UriBuilder;
38import javax.ws.rs.core.UriInfo;
Jian Lie9ac2c52016-01-13 17:42:05 -080039import java.io.IOException;
40import java.io.InputStream;
Jian Lie9ac2c52016-01-13 17:42:05 -080041
Ray Milkeyb784adb2018-04-02 15:33:07 -070042import static org.onlab.util.Tools.readTreeFromStream;
43
Jian Lie9ac2c52016-01-13 17:42:05 -080044/**
45 * Manage flow objectives.
46 */
47@Path("flowobjectives")
48public class FlowObjectiveWebResource extends AbstractWebResource {
49
Jian Li9d616492016-03-09 10:52:49 -080050 @Context
Jian Licc730a62016-05-10 16:36:16 -070051 private UriInfo uriInfo;
Jian Li9d616492016-03-09 10:52:49 -080052
Jian Licc730a62016-05-10 16:36:16 -070053 private static final String DEVICE_INVALID =
Jian Lie9ac2c52016-01-13 17:42:05 -080054 "Invalid deviceId in objective creation request";
Jian Licc730a62016-05-10 16:36:16 -070055 private static final String POLICY_INVALID = "Invalid policy";
Jian Lie9ac2c52016-01-13 17:42:05 -080056
Jian Licc730a62016-05-10 16:36:16 -070057 private final FlowObjectiveService flowObjectiveService = get(FlowObjectiveService.class);
58 private final ObjectNode root = mapper().createObjectNode();
Jian Lie9ac2c52016-01-13 17:42:05 -080059
60 /**
61 * Creates and installs a new filtering objective for the specified device.
62 *
Jian Lia424a052016-05-30 21:02:33 +090063 * @param appId application identifier
Jian Lie9ac2c52016-01-13 17:42:05 -080064 * @param deviceId device identifier
65 * @param stream filtering objective JSON
66 * @return status of the request - CREATED if the JSON is correct,
67 * BAD_REQUEST if the JSON is invalid
68 * @onos.rsModel FilteringObjective
69 */
70 @POST
71 @Path("{deviceId}/filter")
72 @Consumes(MediaType.APPLICATION_JSON)
73 @Produces(MediaType.APPLICATION_JSON)
Jian Lia424a052016-05-30 21:02:33 +090074 public Response createFilteringObjective(@QueryParam("appId") String appId,
75 @PathParam("deviceId") String deviceId,
Jian Lie9ac2c52016-01-13 17:42:05 -080076 InputStream stream) {
Jian Lie9ac2c52016-01-13 17:42:05 -080077 try {
Jian Li9d616492016-03-09 10:52:49 -080078 UriBuilder locationBuilder = null;
Ray Milkeyb784adb2018-04-02 15:33:07 -070079 ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
Ray Milkeyfd4f8d32018-01-17 15:24:52 -080080 validateDeviceId(deviceId, jsonTree);
Jian Lia424a052016-05-30 21:02:33 +090081
Ray Milkeyfd4f8d32018-01-17 15:24:52 -080082 if (appId != null) {
83 jsonTree.put("appId", appId);
Jian Lie9ac2c52016-01-13 17:42:05 -080084 }
Ray Milkeyfd4f8d32018-01-17 15:24:52 -080085
86 DeviceId did = DeviceId.deviceId(deviceId);
87 FilteringObjective filteringObjective =
88 codec(FilteringObjective.class).decode(jsonTree, this);
89 flowObjectiveService.filter(did, filteringObjective);
90 locationBuilder = uriInfo.getBaseUriBuilder()
91 .path("flowobjectives")
92 .path(did.toString())
93 .path("filter")
94 .path(Integer.toString(filteringObjective.id()));
95
Jian Li9d616492016-03-09 10:52:49 -080096 return Response
97 .created(locationBuilder.build())
98 .build();
99 } catch (IOException e) {
Jian Lie9ac2c52016-01-13 17:42:05 -0800100 throw new IllegalArgumentException(e);
101 }
Jian Lie9ac2c52016-01-13 17:42:05 -0800102 }
103
104 /**
105 * Creates and installs a new forwarding objective for the specified device.
106 *
Jian Lia424a052016-05-30 21:02:33 +0900107 * @param appId application identifier
Jian Lie9ac2c52016-01-13 17:42:05 -0800108 * @param deviceId device identifier
109 * @param stream forwarding objective JSON
110 * @return status of the request - CREATED if the JSON is correct,
111 * BAD_REQUEST if the JSON is invalid
112 * @onos.rsModel ForwardingObjective
113 */
114 @POST
115 @Path("{deviceId}/forward")
116 @Consumes(MediaType.APPLICATION_JSON)
117 @Produces(MediaType.APPLICATION_JSON)
Jian Lia424a052016-05-30 21:02:33 +0900118 public Response createForwardingObjective(@QueryParam("appId") String appId,
119 @PathParam("deviceId") String deviceId,
Jian Lie9ac2c52016-01-13 17:42:05 -0800120 InputStream stream) {
Jian Lie9ac2c52016-01-13 17:42:05 -0800121 try {
Jian Li9d616492016-03-09 10:52:49 -0800122 UriBuilder locationBuilder = null;
Jian Lie9ac2c52016-01-13 17:42:05 -0800123 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800124 validateDeviceId(deviceId, jsonTree);
Jian Lia424a052016-05-30 21:02:33 +0900125
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800126 if (appId != null) {
127 jsonTree.put("appId", appId);
Jian Lie9ac2c52016-01-13 17:42:05 -0800128 }
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800129
130 DeviceId did = DeviceId.deviceId(deviceId);
131 ForwardingObjective forwardingObjective =
132 codec(ForwardingObjective.class).decode(jsonTree, this);
133 flowObjectiveService.forward(did, forwardingObjective);
134 locationBuilder = uriInfo.getBaseUriBuilder()
135 .path("flowobjectives")
136 .path(did.toString())
137 .path("forward")
138 .path(Integer.toString(forwardingObjective.id()));
139
Jian Li9d616492016-03-09 10:52:49 -0800140 return Response
141 .created(locationBuilder.build())
142 .build();
143 } catch (IOException e) {
Jian Lie9ac2c52016-01-13 17:42:05 -0800144 throw new IllegalArgumentException(e);
145 }
Jian Lie9ac2c52016-01-13 17:42:05 -0800146 }
147
148 /**
149 * Creates and installs a new next objective for the specified device.
150 *
Jian Lia424a052016-05-30 21:02:33 +0900151 * @param appId application identifier
Jian Lie9ac2c52016-01-13 17:42:05 -0800152 * @param deviceId device identifier
153 * @param stream next objective JSON
154 * @return status of the request - CREATED if the JSON is correct,
155 * BAD_REQUEST if the JSON is invalid
156 * @onos.rsModel NextObjective
157 */
158 @POST
159 @Path("{deviceId}/next")
160 @Consumes(MediaType.APPLICATION_JSON)
161 @Produces(MediaType.APPLICATION_JSON)
Jian Lia424a052016-05-30 21:02:33 +0900162 public Response createNextObjective(@QueryParam("appId") String appId,
163 @PathParam("deviceId") String deviceId,
Jian Lie9ac2c52016-01-13 17:42:05 -0800164 InputStream stream) {
Jian Lie9ac2c52016-01-13 17:42:05 -0800165 try {
Jian Li9d616492016-03-09 10:52:49 -0800166 UriBuilder locationBuilder = null;
Jian Lie9ac2c52016-01-13 17:42:05 -0800167 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800168 validateDeviceId(deviceId, jsonTree);
Jian Lia424a052016-05-30 21:02:33 +0900169
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800170 if (appId != null) {
171 jsonTree.put("appId", appId);
Jian Lie9ac2c52016-01-13 17:42:05 -0800172 }
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800173
174 DeviceId did = DeviceId.deviceId(deviceId);
175 NextObjective nextObjective =
176 codec(NextObjective.class).decode(jsonTree, this);
177 flowObjectiveService.next(did, nextObjective);
178 locationBuilder = uriInfo.getBaseUriBuilder()
179 .path("flowobjectives")
180 .path(did.toString())
181 .path("next")
182 .path(Integer.toString(nextObjective.id()));
183
Jian Li9d616492016-03-09 10:52:49 -0800184 return Response
185 .created(locationBuilder.build())
186 .build();
187 } catch (IOException e) {
Jian Lie9ac2c52016-01-13 17:42:05 -0800188 throw new IllegalArgumentException(e);
189 }
Jian Lie9ac2c52016-01-13 17:42:05 -0800190 }
191
192 /**
193 * Returns the globally unique nextId.
194 *
Jian Licc730a62016-05-10 16:36:16 -0700195 * @return 200 OK with next identifier
Jian Lid79d39e2016-02-01 12:53:47 -0800196 * @onos.rsModel NextId
Jian Lie9ac2c52016-01-13 17:42:05 -0800197 */
198 @GET
199 @Path("next")
200 @Produces(MediaType.APPLICATION_JSON)
201 public Response getNextId() {
202 root.put("nextId", flowObjectiveService.allocateNextId());
203 return ok(root).build();
204 }
205
206 /**
207 * Installs the filtering rules onto the specified device.
208 *
209 * @param stream filtering rule JSON
Jian Licc730a62016-05-10 16:36:16 -0700210 * @return 200 OK
Jian Lie9ac2c52016-01-13 17:42:05 -0800211 * @onos.rsModel ObjectivePolicy
212 */
213 @POST
214 @Path("policy")
215 @Consumes(MediaType.APPLICATION_JSON)
Jian Licc730a62016-05-10 16:36:16 -0700216 public Response initPolicy(InputStream stream) {
Jian Lie9ac2c52016-01-13 17:42:05 -0800217
218 try {
219 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
220 JsonNode policyJson = jsonTree.get("policy");
221
222 if (policyJson == null || policyJson.asText().isEmpty()) {
223 throw new IllegalArgumentException(POLICY_INVALID);
224 }
225
226 flowObjectiveService.initPolicy(policyJson.asText());
Jian Licc730a62016-05-10 16:36:16 -0700227 return Response.ok().build();
Jian Lie9ac2c52016-01-13 17:42:05 -0800228 } catch (IOException e) {
229 throw new IllegalArgumentException(e);
230 }
231 }
232
233 /**
Jian Licc730a62016-05-10 16:36:16 -0700234 * Validates the deviceId that is contained in json string against the
Jian Lie9ac2c52016-01-13 17:42:05 -0800235 * input deviceId.
236 *
237 * @param deviceId device identifier
238 * @param node object node
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800239 * @throws IllegalArgumentException if the device id is invalid
Jian Lie9ac2c52016-01-13 17:42:05 -0800240 */
Ray Milkeyfd4f8d32018-01-17 15:24:52 -0800241 private void validateDeviceId(String deviceId, ObjectNode node) {
Jian Lie9ac2c52016-01-13 17:42:05 -0800242 JsonNode specifiedDeviceId = node.get("deviceId");
243
244 if (specifiedDeviceId != null &&
245 !specifiedDeviceId.asText().equals(deviceId)) {
246 throw new IllegalArgumentException(DEVICE_INVALID);
247 }
Jian Lie9ac2c52016-01-13 17:42:05 -0800248 }
249}