blob: 52d4150e23a04e75c900746e99b42e0cc3202c30 [file] [log] [blame]
Sean Condon0e89bda2017-03-21 14:23:19 +00001/*
2 * Copyright 2017-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 */
Sean Condon081290d2017-11-02 13:15:08 +000016package org.onosproject.cfm.rest;
Sean Condon0e89bda2017-03-21 14:23:19 +000017
18import java.io.InputStream;
19import java.net.URI;
20import java.util.Collection;
Sean Condon96b896d2017-12-11 12:44:29 -080021import java.util.Optional;
Sean Condon0e89bda2017-03-21 14:23:19 +000022
23import javax.ws.rs.Consumes;
24import javax.ws.rs.DELETE;
25import javax.ws.rs.GET;
26import javax.ws.rs.POST;
27import javax.ws.rs.PUT;
28import javax.ws.rs.Path;
29import javax.ws.rs.PathParam;
30import javax.ws.rs.Produces;
31import javax.ws.rs.core.MediaType;
32import javax.ws.rs.core.Response;
33
34import org.onosproject.cfm.web.MepCodec;
35import org.onosproject.codec.JsonCodec;
36import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
37import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
38import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
39import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
40import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
41import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
42import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
43import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
44import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
45import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
46import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
47import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
48import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
49import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
50import org.onosproject.rest.AbstractWebResource;
51import org.slf4j.Logger;
52import org.slf4j.LoggerFactory;
53
54import com.fasterxml.jackson.databind.JsonNode;
55import com.fasterxml.jackson.databind.ObjectMapper;
56import com.fasterxml.jackson.databind.node.ArrayNode;
57import com.fasterxml.jackson.databind.node.ObjectNode;
58
59/**
60 * Layer 2 CFM Maintenance Association Endpoint (MEP) web resource.
61 */
62@Path("md/{md_name}/ma/{ma_name}/mep")
63public class MepWebResource extends AbstractWebResource {
64 private final Logger log = LoggerFactory.getLogger(getClass());
65
66 /**
67 * Get all MEPs by MD name, MA name.
68 *
69 * @param mdName The name of a Maintenance Domain
70 * @param maName The name of a Maintenance Association belonging to the MD
71 * @return 200 OK with a list of MEPS or 500 on error
72 */
73 @GET
74 @Produces(MediaType.APPLICATION_JSON)
75 @Consumes(MediaType.APPLICATION_JSON)
76 public Response getAllMepsForMa(@PathParam("md_name") String mdName,
77 @PathParam("ma_name") String maName) {
78 log.debug("GET all Meps called for MA {}", mdName + "/" + maName);
79 try {
80 MdId mdId = MdIdCharStr.asMdId(mdName);
81 MaIdShort maId = MaIdCharStr.asMaId(maName);
82 Collection<MepEntry> mepCollection = get(CfmMepService.class).getAllMeps(mdId, maId);
83 ArrayNode an = mapper().createArrayNode();
84 an.add(codec(MepEntry.class).encode(mepCollection, this));
85 return ok(mapper().createObjectNode().set("meps", an)).build();
86 } catch (CfmConfigException e) {
87 log.error("Get all Meps on {} failed because of exception",
88 mdName + "/" + maName, e);
89 return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build();
90 }
91
92 }
93
94 /**
95 * Get MEP by MD name, MA name and Mep Id.
96 *
97 * @param mdName The name of a Maintenance Domain
98 * @param maName The name of a Maintenance Association belonging to the MD
99 * @param mepId The Id of the MEP
100 * @return 200 OK with details of the MEP or 500 on error
101 */
102 @GET
103 @Path("{mep_id}")
104 @Produces(MediaType.APPLICATION_JSON)
105 @Consumes(MediaType.APPLICATION_JSON)
106 public Response getMep(@PathParam("md_name") String mdName,
107 @PathParam("ma_name") String maName,
108 @PathParam("mep_id") short mepId) {
109 log.debug("GET called for MEP {}", mdName + "/" + maName + "/" + mepId);
110 try {
111 MdId mdId = MdIdCharStr.asMdId(mdName);
112 MaIdShort maId = MaIdCharStr.asMaId(maName);
113 MepEntry mepEntry = get(CfmMepService.class)
114 .getMep(mdId, maId, MepId.valueOf(mepId));
115 if (mepEntry == null) {
116 return Response.serverError().entity("{ \"failure\":\"MEP " +
117 mdName + "/" + maName + "/" + mepId + " not found\" }").build();
118 }
119 ObjectNode node = mapper().createObjectNode();
120 node.set("mep", codec(MepEntry.class).encode(mepEntry, this));
121 return ok(node).build();
122 } catch (CfmConfigException e) {
123 log.error("Get Mep {} failed because of exception",
124 mdName + "/" + maName + "/" + mepId, e);
125 return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build();
126 }
127 }
128
129 /**
130 * Delete MEP by MD name, MA name and Mep Id.
131 *
132 * @param mdName The name of a Maintenance Domain
133 * @param maName The name of a Maintenance Association belonging to the MD
134 * @param mepIdShort The Id of the MEP
135 * @return 200 OK or 304 if not found, or 500 on error
136 */
137 @DELETE
138 @Path("{mep_id}")
139 @Consumes(MediaType.APPLICATION_JSON)
140 @Produces(MediaType.APPLICATION_JSON)
141 public Response deleteMep(@PathParam("md_name") String mdName,
142 @PathParam("ma_name") String maName,
143 @PathParam("mep_id") short mepIdShort) {
144 log.debug("DELETE called for MEP " + mdName + "/" + maName + "/" + mepIdShort);
145 try {
146 MdId mdId = MdIdCharStr.asMdId(mdName);
147 MaIdShort maId = MaIdCharStr.asMaId(maName);
148 boolean deleted = get(CfmMepService.class)
Sean Condon96b896d2017-12-11 12:44:29 -0800149 .deleteMep(mdId, maId, MepId.valueOf(mepIdShort), Optional.empty());
Sean Condon0e89bda2017-03-21 14:23:19 +0000150 if (!deleted) {
151 return Response.notModified(mdName + "/" + maName + "/" +
152 mepIdShort + " did not exist").build();
153 } else {
154 return ok("{ \"success\":\"deleted " + mdName + "/" + maName +
155 "/" + mepIdShort + "\" }").build();
156 }
157 } catch (CfmConfigException e) {
158 log.error("Delete Mep {} failed because of exception ",
159 mdName + "/" + maName + "/" + mepIdShort, e);
160 return Response.serverError().entity("{ \"failure\":\"" +
161 e.toString() + "\" }").build();
162 }
163 }
164
165 /**
166 * Create MEP with MD name, MA name and Mep Json.
167 *
Sean Condon081290d2017-11-02 13:15:08 +0000168 * @onos.rsModel MepCreate
Sean Condon0e89bda2017-03-21 14:23:19 +0000169 * @param mdName The name of a Maintenance Domain
170 * @param maName The name of a Maintenance Association belonging to the MD
171 * @param input A JSON formatted input stream specifying the Mep parameters
172 * @return 201 Created or 304 if already exists or 500 on error
173 */
174 @POST
175 @Consumes(MediaType.APPLICATION_JSON)
176 @Produces(MediaType.APPLICATION_JSON)
177 public Response createMep(@PathParam("md_name") String mdName,
178 @PathParam("ma_name") String maName, InputStream input) {
179 log.debug("POST called to Create Mep");
180 try {
181 MdId mdId = MdIdCharStr.asMdId(mdName);
182 MaIdShort maId = MaIdCharStr.asMaId(maName);
183 MaintenanceAssociation ma = get(CfmMdService.class).getMaintenanceAssociation(mdId, maId).get();
184
185 ObjectMapper mapper = new ObjectMapper();
186 JsonNode cfg = mapper.readTree(input);
187 JsonCodec<Mep> mepCodec = codec(Mep.class);
188
189 Mep mep = ((MepCodec) mepCodec).decode((ObjectNode) cfg, this, mdName, maName);
190
Sean Condon96b896d2017-12-11 12:44:29 -0800191 Boolean didNotExist = get(CfmMepService.class).createMep(mdId, maId, mep);
192 if (!didNotExist) {
Sean Condon0e89bda2017-03-21 14:23:19 +0000193 return Response.notModified(mdName + "/" + ma.maId() + "/" + mep.mepId() +
194 " already exists").build();
195 }
196 return Response
197 .created(new URI("md/" + mdName + "/ma/" + ma.maId() + "/mep/" + mep.mepId()))
198 .entity("{ \"success\":\"mep " + mdName + "/" + ma.maId() + "/" + mep.mepId() + " created\" }")
199 .build();
200 } catch (Exception | CfmConfigException e) {
201 log.error("Create Mep on " + mdName + "/" + maName + " failed because of exception {}",
202 e.toString());
203 return Response.serverError()
204 .entity("{ \"failure\":\"" + e.toString() + "\" }")
205 .build();
206 }
207 }
208
209 /**
210 * Transmit Loopback on MEP with MD name, MA name and Mep Id.
211 *
Sean Condon081290d2017-11-02 13:15:08 +0000212 * @onos.rsModel MepLbTransmit
Sean Condon0e89bda2017-03-21 14:23:19 +0000213 * @param mdName The name of a Maintenance Domain
214 * @param maName The name of a Maintenance Association belonging to the MD
215 * @param mepIdShort The id of a MEP belonging to the MA
216 * @param input A JSON formatted input stream specifying the Mep parameters
217 * @return 202 Received with success message or 500 on error
218 */
219 @PUT
220 @Path("{mep_id}/transmit-loopback")
221 @Consumes(MediaType.APPLICATION_JSON)
222 @Produces(MediaType.APPLICATION_JSON)
223 public Response transmitLoopback(
224 @PathParam("md_name") String mdName,
225 @PathParam("ma_name") String maName,
226 @PathParam("mep_id") short mepIdShort,
227 InputStream input) {
228 log.debug("PUT called to Transmit Loopback on Mep");
229
230 MdId mdId = MdIdCharStr.asMdId(mdName);
231 MaIdShort maId = MaIdCharStr.asMaId(maName);
232 MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get();
233 MaintenanceAssociation ma = get(CfmMdService.class)
234 .getMaintenanceAssociation(mdId, maId).get();
235
236 MepId mepId = MepId.valueOf(mepIdShort);
237
238 try {
239 ObjectMapper mapper = new ObjectMapper();
240 JsonNode cfg = mapper.readTree(input);
241 JsonCodec<MepLbCreate> mepLbCreateCodec = codec(MepLbCreate.class);
242
243 MepLbCreate lbCreate = mepLbCreateCodec.decode((ObjectNode) cfg, this);
244 get(CfmMepService.class).transmitLoopback(md.mdId(), ma.maId(), mepId, lbCreate);
245 } catch (Exception | CfmConfigException e) {
246 log.error("Transmit Loopback on " + mdName + "/" + maName +
247 "/{} failed", String.valueOf(mepIdShort), e);
248 return Response.serverError()
249 .entity("{ \"failure\":\"" + e.toString() + "\" }")
250 .build();
251 }
252
253 return Response.accepted()
254 .entity("{ \"success\":\"Loopback on MEP " + mdName + "/" + ma.maId() + "/"
255 + mepId.id() + " started\" }").build();
256 }
257
258 /**
259 * Abort Loopback on MEP with MD name, MA name and Mep Id.
260 *
261 * @param mdName The name of a Maintenance Domain
262 * @param maName The name of a Maintenance Association belonging to the MD
263 * @param mepIdShort The id of a MEP belonging to the MA
264 * @return 202 Received with success message or 500 on error
265 */
266 @PUT
267 @Path("{mep_id}/abort-loopback")
268 @Consumes(MediaType.APPLICATION_JSON)
269 @Produces(MediaType.APPLICATION_JSON)
270 public Response abortLoopback(
271 @PathParam("md_name") String mdName,
272 @PathParam("ma_name") String maName,
273 @PathParam("mep_id") short mepIdShort) {
274 log.debug("PUT called to Abort Loopback on Mep");
275
276 MdId mdId = MdIdCharStr.asMdId(mdName);
277 MaIdShort maId = MaIdCharStr.asMaId(maName);
278 MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get();
279 MaintenanceAssociation ma = get(CfmMdService.class)
280 .getMaintenanceAssociation(mdId, maId).get();
281
282 MepId mepId = MepId.valueOf(mepIdShort);
283
284 try {
285 get(CfmMepService.class).abortLoopback(md.mdId(), ma.maId(), mepId);
286 } catch (CfmConfigException e) {
287 log.error("Abort Loopback on " + mdName + "/" + maName +
288 "/{} failed", String.valueOf(mepIdShort), e);
289 return Response.serverError()
290 .entity("{ \"failure\":\"" + e.toString() + "\" }")
291 .build();
292 }
293
294 return Response.accepted()
295 .entity("{ \"success\":\"Loopback on MEP " + mdName + "/" + ma.maId() + "/"
296 + mepId.id() + " aborted\" }").build();
297 }
298
299 /**
300 * Transmit Linktrace on MEP with MD name, MA name and Mep Id.
301 *
Sean Condon081290d2017-11-02 13:15:08 +0000302 * @onos.rsModel MepLtTransmit
Sean Condon0e89bda2017-03-21 14:23:19 +0000303 * @param mdName The name of a Maintenance Domain
304 * @param maName The name of a Maintenance Association belonging to the MD
305 * @param mepIdShort The id of a MEP belonging to the MA
306 * @param input A JSON formatted input stream specifying the Linktrace parameters
307 * @return 202 Received with success message or 500 on error
308 */
309 @PUT
310 @Path("{mep_id}/transmit-linktrace")
311 @Consumes(MediaType.APPLICATION_JSON)
312 @Produces(MediaType.APPLICATION_JSON)
313 public Response transmitLinktrace(
314 @PathParam("md_name") String mdName,
315 @PathParam("ma_name") String maName,
316 @PathParam("mep_id") short mepIdShort,
317 InputStream input) {
318 log.debug("PUT called to Transmit Linktrace on Mep");
319
320 MdId mdId = MdIdCharStr.asMdId(mdName);
321 MaIdShort maId = MaIdCharStr.asMaId(maName);
322 MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get();
323 MaintenanceAssociation ma = get(CfmMdService.class)
324 .getMaintenanceAssociation(mdId, maId).get();
325
326 MepId mepId = MepId.valueOf(mepIdShort);
327
328 try {
329 ObjectMapper mapper = new ObjectMapper();
330 JsonNode cfg = mapper.readTree(input);
331 JsonCodec<MepLtCreate> mepLtCreateCodec = codec(MepLtCreate.class);
332
333 MepLtCreate ltCreate = mepLtCreateCodec.decode((ObjectNode) cfg, this);
334 get(CfmMepService.class).transmitLinktrace(md.mdId(), ma.maId(), mepId, ltCreate);
335 } catch (Exception | CfmConfigException e) {
336 log.error("Transmit Linktrace on " + mdName + "/" + maName +
337 "/{} failed", String.valueOf(mepIdShort), e);
338 return Response.serverError()
339 .entity("{ \"failure\":\"" + e.toString() + "\" }")
340 .build();
341 }
342
343 return Response.accepted()
344 .entity("{ \"success\":\"Linktrace on MEP " + mdName + "/" + ma.maId() + "/"
345 + mepId.id() + " started\" }").build();
346 }
347}