blob: 1d8bb76967b52685621bc1c4736fca2db938158d [file] [log] [blame]
Andreas Pantelopouloscd339592018-02-23 14:18:00 -08001/*
2 * Copyright 2015-present Open Networking Foundation
3 *
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.segmentrouting.web;
17
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -070018import com.fasterxml.jackson.databind.JsonNode;
Andreas Pantelopouloscd339592018-02-23 14:18:00 -080019import com.fasterxml.jackson.databind.ObjectMapper;
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -070020import com.fasterxml.jackson.databind.node.ArrayNode;
Andreas Pantelopouloscd339592018-02-23 14:18:00 -080021import com.fasterxml.jackson.databind.node.ObjectNode;
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -070022import org.onlab.util.ItemNotFoundException;
Andreas Pantelopouloscd339592018-02-23 14:18:00 -080023import org.onosproject.rest.AbstractWebResource;
24import org.onosproject.segmentrouting.SegmentRoutingService;
25import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
26import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
27import org.onosproject.segmentrouting.pwaas.L2Tunnel;
28import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
29import org.slf4j.Logger;
30import org.slf4j.LoggerFactory;
31
32import javax.ws.rs.Consumes;
33import javax.ws.rs.DELETE;
34import javax.ws.rs.GET;
35import javax.ws.rs.POST;
36import javax.ws.rs.Path;
37import javax.ws.rs.Produces;
38import javax.ws.rs.core.MediaType;
39import javax.ws.rs.core.Response;
40import java.io.IOException;
41import java.io.InputStream;
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -070042import java.util.ArrayList;
Andreas Pantelopouloscd339592018-02-23 14:18:00 -080043import java.util.List;
44import java.util.stream.Collectors;
45
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -070046import static org.onlab.util.Tools.nullIsIllegal;
Ray Milkey86ee5e82018-04-02 15:33:07 -070047import static org.onlab.util.Tools.readTreeFromStream;
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -070048
Andreas Pantelopouloscd339592018-02-23 14:18:00 -080049/**
50 * Query, create and remove pseudowires.
51 */
52@Path("pseudowire")
53public class PseudowireWebResource extends AbstractWebResource {
54
55 private static final PseudowireCodec PSEUDOWIRE_CODEC = new PseudowireCodec();
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -070056 public static final String PWS = "pseudowires";
57 private static final String PWS_KEY_ERROR = "Pseudowires key must be present.";
Andreas Pantelopouloscd339592018-02-23 14:18:00 -080058
59 private static Logger log = LoggerFactory
60 .getLogger(PseudowireWebResource.class);
61
62 /**
63 * Get all pseudowires.
64 * Returns an array of pseudowires.
65 *
66 * @return status of OK
67 */
68 @GET
69 @Produces(MediaType.APPLICATION_JSON)
70 public Response getPseudowire() {
71 SegmentRoutingService srService = get(SegmentRoutingService.class);
72
73 log.debug("Fetching pseudowires form rest api!");
74
75 List<L2TunnelPolicy> policies = srService.getL2Policies();
76 List<L2Tunnel> tunnels = srService.getL2Tunnels();
77 List<DefaultL2TunnelDescription> pseudowires = tunnels.stream()
78 .map(l2Tunnel -> {
79 L2TunnelPolicy policy = null;
80 for (L2TunnelPolicy l2Policy : policies) {
81 if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
82 policy = l2Policy;
83 break;
84 }
85 }
86
87 // return a copy
88 return new DefaultL2TunnelDescription(l2Tunnel, policy);
89 })
90 .collect(Collectors.toList());
91
92 ObjectNode result = new ObjectMapper().createObjectNode();
93 result.set("pseudowires", new PseudowireCodec().encode(pseudowires, this));
94
95 return ok(result.toString()).build();
96 }
97
98 /**
99 * Create a new pseudowire.
100 *
101 * @param input JSON stream for pseudowire to create
102 * @return Response with appropriate status
103 * @throws IOException Throws IO exception.
104 * @onos.rsModel PseudowireCreate
105 */
106 @POST
107 @Consumes(MediaType.APPLICATION_JSON)
108 public Response createPseudowire(InputStream input) throws IOException {
109
110 ObjectMapper mapper = new ObjectMapper();
Ray Milkey86ee5e82018-04-02 15:33:07 -0700111 ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
Andreas Pantelopouloscd339592018-02-23 14:18:00 -0800112 SegmentRoutingService srService = get(SegmentRoutingService.class);
113
114 DefaultL2TunnelDescription pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
115 if (pseudowire == null) {
116 return Response.serverError().status(Response.Status.BAD_REQUEST).build();
117 }
118
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700119 log.debug("Creating pseudowire {} from rest api!", pseudowire.l2Tunnel().tunnelId());
Andreas Pantelopouloscd339592018-02-23 14:18:00 -0800120
121 L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
122 switch (res) {
123 case ADDITION_ERROR:
124 log.error("Pseudowire {} could not be added, error in configuration," +
125 " please check logs for more details!",
126 pseudowire.l2Tunnel().tunnelId());
127 return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build();
128
129 case SUCCESS:
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700130 log.debug("Pseudowire {} succesfully deployed!", pseudowire.l2Tunnel().tunnelId());
131 return Response.ok().build();
132 default:
133 return Response.ok().build();
134 }
135 }
136
137 /**
138 * Create a bulk of pseudowires.
139 *
140 * @param input JSON stream for pseudowires to create
141 * @return Response with appropriate status
142 * @throws IOException Throws IO exception.
143 * @onos.rsModel PseudowireCreateBulk
144 */
145 @POST
146 @Path("/bulk")
147 @Consumes(MediaType.APPLICATION_JSON)
148 public Response createPseudowiresBulk(InputStream input) throws IOException {
149
150 ObjectMapper mapper = new ObjectMapper();
Ray Milkey86ee5e82018-04-02 15:33:07 -0700151 ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700152 SegmentRoutingService srService = get(SegmentRoutingService.class);
153 List<DefaultL2TunnelDescription> pseudowires;
154
155 try {
156 ArrayNode pseudowiresArray = nullIsIllegal((ArrayNode) pseudowireJson.get(PWS), PWS_KEY_ERROR);
157 pseudowires = PSEUDOWIRE_CODEC.decode(pseudowiresArray, this);
158 } catch (ItemNotFoundException e) {
159 return Response.serverError().status(Response.Status.BAD_REQUEST).build();
160 }
161
162 log.debug("Creating pseudowires {} from rest api!", pseudowires);
163
164 L2TunnelHandler.Result res = srService.addPseudowiresBulk(pseudowires);
165 switch (res) {
166 case ADDITION_ERROR:
167 log.error("Bulk of pseudowires {} could not be added, error in configuration," +
168 " please check logs for more details!",
169 pseudowires);
170 return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build();
171
172 case SUCCESS:
173 log.debug("Bulk of pseudowires {} succesfully deployed!", pseudowires);
Andreas Pantelopouloscd339592018-02-23 14:18:00 -0800174 return Response.ok().build();
175 default:
176 return Response.ok().build();
177 }
178 }
179
180 /**
181 * Delete a pseudowire.
182 *
183 * @param input JSON stream for pseudowire to delete
184 * @return Response with appropriate status
185 * @throws IOException Throws IO exception.
186 * @onos.rsModel PseudowireDelete
187 */
188 @DELETE
189 @Consumes(MediaType.APPLICATION_JSON)
190 public Response removePseudowire(InputStream input) throws IOException {
191
192 ObjectMapper mapper = new ObjectMapper();
Ray Milkey86ee5e82018-04-02 15:33:07 -0700193 ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
Andreas Pantelopouloscd339592018-02-23 14:18:00 -0800194 SegmentRoutingService srService = get(SegmentRoutingService.class);
195
196 Integer pseudowireId = PSEUDOWIRE_CODEC.decodeId(pseudowireJson);
197 if (pseudowireId == null) {
198 return Response.serverError().status(Response.Status.BAD_REQUEST).build();
199 }
200
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700201 log.debug("Deleting pseudowire {} from rest api!", pseudowireId);
Andreas Pantelopouloscd339592018-02-23 14:18:00 -0800202
203 L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
204 switch (res) {
205 case REMOVAL_ERROR:
206 log.error("Pseudowire {} could not be removed, error in configuration," +
207 " please check logs for more details!",
208 pseudowireId);
209
210 return Response.noContent().build();
211 case SUCCESS:
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700212 log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
Andreas Pantelopouloscd339592018-02-23 14:18:00 -0800213 return Response.noContent().build();
214 default:
215 return Response.noContent().build();
216 }
217 }
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700218
219 /**
220 * Delete a bulk of pseudowires.
221 *
222 * @param input JSON stream for pseudowires to delete
223 * @return Response with appropriate status
224 * @throws IOException Throws IO exception.
225 * @onos.rsModel PseudowireDeleteBulk
226 */
227 @DELETE
228 @Path("/bulk")
229 @Consumes(MediaType.APPLICATION_JSON)
230 public Response removePseudowiresBulk(InputStream input) throws IOException {
231
232 ObjectMapper mapper = new ObjectMapper();
Ray Milkey86ee5e82018-04-02 15:33:07 -0700233 ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700234 SegmentRoutingService srService = get(SegmentRoutingService.class);
235
236 List<Integer> ids = new ArrayList<>();
237
238 // try to parse all ids, if key is not present, or if an id is not an int
239 // throw an exception and stop process
240 try {
241 for (JsonNode node : pseudowireJson.withArray(PWS)) {
242 Integer idToDelete = PseudowireCodec.decodeId((ObjectNode) node);
243 if (idToDelete == null) {
244 log.error("Error when parsing pseudowire for deletion in REST API.");
245 throw new IllegalArgumentException("Id of pseudowire should be an integer!");
246 }
247 ids.add(idToDelete);
248 }
249 } catch (IllegalArgumentException e) {
250 log.error("Pseudowire ID should be an integer.");
251 return Response.serverError().status(Response.Status.BAD_REQUEST).build();
252 } catch (UnsupportedOperationException e) {
253 log.error("Pseudowires for deletion should be an array of pseudowire ids.");
254 return Response.serverError().status(Response.Status.BAD_REQUEST).build();
255 }
256
257 for (Integer pseudowireId : ids) {
258 L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
259 switch (res) {
260 case REMOVAL_ERROR:
261 log.error("Pseudowire {} could not be removed, error in configuration," +
262 " please check logs for more details!",
263 pseudowireId);
Ray Milkeyb994f8d2018-03-14 09:55:13 -0700264 break;
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700265 case SUCCESS:
266 log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
Ray Milkeyb994f8d2018-03-14 09:55:13 -0700267 break;
Andreas Pantelopoulosff691b72018-03-12 16:30:20 -0700268 default:
269 }
270 }
271
272 return Response.noContent().build();
273 }
Andreas Pantelopouloscd339592018-02-23 14:18:00 -0800274}