Initial import of CFM and SOAM api
Change-Id: Icf5cc2d5fb34b75460e80e8cced0d70265bcd33b
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/impl/MepWebResource.java b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MepWebResource.java
new file mode 100644
index 0000000..2486df0
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MepWebResource.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfm.impl;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Collection;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.cfm.web.MepCodec;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
+import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Layer 2 CFM Maintenance Association Endpoint (MEP) web resource.
+ */
+@Path("md/{md_name}/ma/{ma_name}/mep")
+public class MepWebResource extends AbstractWebResource {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * Get all MEPs by MD name, MA name.
+ *
+ * @param mdName The name of a Maintenance Domain
+ * @param maName The name of a Maintenance Association belonging to the MD
+ * @return 200 OK with a list of MEPS or 500 on error
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response getAllMepsForMa(@PathParam("md_name") String mdName,
+ @PathParam("ma_name") String maName) {
+ log.debug("GET all Meps called for MA {}", mdName + "/" + maName);
+ try {
+ MdId mdId = MdIdCharStr.asMdId(mdName);
+ MaIdShort maId = MaIdCharStr.asMaId(maName);
+ Collection<MepEntry> mepCollection = get(CfmMepService.class).getAllMeps(mdId, maId);
+ ArrayNode an = mapper().createArrayNode();
+ an.add(codec(MepEntry.class).encode(mepCollection, this));
+ return ok(mapper().createObjectNode().set("meps", an)).build();
+ } catch (CfmConfigException e) {
+ log.error("Get all Meps on {} failed because of exception",
+ mdName + "/" + maName, e);
+ return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build();
+ }
+
+ }
+
+ /**
+ * Get MEP by MD name, MA name and Mep Id.
+ *
+ * @param mdName The name of a Maintenance Domain
+ * @param maName The name of a Maintenance Association belonging to the MD
+ * @param mepId The Id of the MEP
+ * @return 200 OK with details of the MEP or 500 on error
+ */
+ @GET
+ @Path("{mep_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response getMep(@PathParam("md_name") String mdName,
+ @PathParam("ma_name") String maName,
+ @PathParam("mep_id") short mepId) {
+ log.debug("GET called for MEP {}", mdName + "/" + maName + "/" + mepId);
+ try {
+ MdId mdId = MdIdCharStr.asMdId(mdName);
+ MaIdShort maId = MaIdCharStr.asMaId(maName);
+ MepEntry mepEntry = get(CfmMepService.class)
+ .getMep(mdId, maId, MepId.valueOf(mepId));
+ if (mepEntry == null) {
+ return Response.serverError().entity("{ \"failure\":\"MEP " +
+ mdName + "/" + maName + "/" + mepId + " not found\" }").build();
+ }
+ ObjectNode node = mapper().createObjectNode();
+ node.set("mep", codec(MepEntry.class).encode(mepEntry, this));
+ return ok(node).build();
+ } catch (CfmConfigException e) {
+ log.error("Get Mep {} failed because of exception",
+ mdName + "/" + maName + "/" + mepId, e);
+ return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build();
+ }
+ }
+
+ /**
+ * Delete MEP by MD name, MA name and Mep Id.
+ *
+ * @param mdName The name of a Maintenance Domain
+ * @param maName The name of a Maintenance Association belonging to the MD
+ * @param mepIdShort The Id of the MEP
+ * @return 200 OK or 304 if not found, or 500 on error
+ */
+ @DELETE
+ @Path("{mep_id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response deleteMep(@PathParam("md_name") String mdName,
+ @PathParam("ma_name") String maName,
+ @PathParam("mep_id") short mepIdShort) {
+ log.debug("DELETE called for MEP " + mdName + "/" + maName + "/" + mepIdShort);
+ try {
+ MdId mdId = MdIdCharStr.asMdId(mdName);
+ MaIdShort maId = MaIdCharStr.asMaId(maName);
+ boolean deleted = get(CfmMepService.class)
+ .deleteMep(mdId, maId, MepId.valueOf(mepIdShort));
+ if (!deleted) {
+ return Response.notModified(mdName + "/" + maName + "/" +
+ mepIdShort + " did not exist").build();
+ } else {
+ return ok("{ \"success\":\"deleted " + mdName + "/" + maName +
+ "/" + mepIdShort + "\" }").build();
+ }
+ } catch (CfmConfigException e) {
+ log.error("Delete Mep {} failed because of exception ",
+ mdName + "/" + maName + "/" + mepIdShort, e);
+ return Response.serverError().entity("{ \"failure\":\"" +
+ e.toString() + "\" }").build();
+ }
+ }
+
+ /**
+ * Create MEP with MD name, MA name and Mep Json.
+ *
+ * @param mdName The name of a Maintenance Domain
+ * @param maName The name of a Maintenance Association belonging to the MD
+ * @param input A JSON formatted input stream specifying the Mep parameters
+ * @return 201 Created or 304 if already exists or 500 on error
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createMep(@PathParam("md_name") String mdName,
+ @PathParam("ma_name") String maName, InputStream input) {
+ log.debug("POST called to Create Mep");
+ try {
+ MdId mdId = MdIdCharStr.asMdId(mdName);
+ MaIdShort maId = MaIdCharStr.asMaId(maName);
+ MaintenanceAssociation ma = get(CfmMdService.class).getMaintenanceAssociation(mdId, maId).get();
+
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode cfg = mapper.readTree(input);
+ JsonCodec<Mep> mepCodec = codec(Mep.class);
+
+ Mep mep = ((MepCodec) mepCodec).decode((ObjectNode) cfg, this, mdName, maName);
+
+ Boolean issuccess = get(CfmMepService.class).createMep(mdId, maId, mep);
+ if (!issuccess) {
+ return Response.notModified(mdName + "/" + ma.maId() + "/" + mep.mepId() +
+ " already exists").build();
+ }
+ return Response
+ .created(new URI("md/" + mdName + "/ma/" + ma.maId() + "/mep/" + mep.mepId()))
+ .entity("{ \"success\":\"mep " + mdName + "/" + ma.maId() + "/" + mep.mepId() + " created\" }")
+ .build();
+ } catch (Exception | CfmConfigException e) {
+ log.error("Create Mep on " + mdName + "/" + maName + " failed because of exception {}",
+ e.toString());
+ return Response.serverError()
+ .entity("{ \"failure\":\"" + e.toString() + "\" }")
+ .build();
+ }
+ }
+
+ /**
+ * Transmit Loopback on MEP with MD name, MA name and Mep Id.
+ *
+ * @param mdName The name of a Maintenance Domain
+ * @param maName The name of a Maintenance Association belonging to the MD
+ * @param mepIdShort The id of a MEP belonging to the MA
+ * @param input A JSON formatted input stream specifying the Mep parameters
+ * @return 202 Received with success message or 500 on error
+ */
+ @PUT
+ @Path("{mep_id}/transmit-loopback")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response transmitLoopback(
+ @PathParam("md_name") String mdName,
+ @PathParam("ma_name") String maName,
+ @PathParam("mep_id") short mepIdShort,
+ InputStream input) {
+ log.debug("PUT called to Transmit Loopback on Mep");
+
+ MdId mdId = MdIdCharStr.asMdId(mdName);
+ MaIdShort maId = MaIdCharStr.asMaId(maName);
+ MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get();
+ MaintenanceAssociation ma = get(CfmMdService.class)
+ .getMaintenanceAssociation(mdId, maId).get();
+
+ MepId mepId = MepId.valueOf(mepIdShort);
+
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode cfg = mapper.readTree(input);
+ JsonCodec<MepLbCreate> mepLbCreateCodec = codec(MepLbCreate.class);
+
+ MepLbCreate lbCreate = mepLbCreateCodec.decode((ObjectNode) cfg, this);
+ get(CfmMepService.class).transmitLoopback(md.mdId(), ma.maId(), mepId, lbCreate);
+ } catch (Exception | CfmConfigException e) {
+ log.error("Transmit Loopback on " + mdName + "/" + maName +
+ "/{} failed", String.valueOf(mepIdShort), e);
+ return Response.serverError()
+ .entity("{ \"failure\":\"" + e.toString() + "\" }")
+ .build();
+ }
+
+ return Response.accepted()
+ .entity("{ \"success\":\"Loopback on MEP " + mdName + "/" + ma.maId() + "/"
+ + mepId.id() + " started\" }").build();
+ }
+
+ /**
+ * Abort Loopback on MEP with MD name, MA name and Mep Id.
+ *
+ * @param mdName The name of a Maintenance Domain
+ * @param maName The name of a Maintenance Association belonging to the MD
+ * @param mepIdShort The id of a MEP belonging to the MA
+ * @return 202 Received with success message or 500 on error
+ */
+ @PUT
+ @Path("{mep_id}/abort-loopback")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response abortLoopback(
+ @PathParam("md_name") String mdName,
+ @PathParam("ma_name") String maName,
+ @PathParam("mep_id") short mepIdShort) {
+ log.debug("PUT called to Abort Loopback on Mep");
+
+ MdId mdId = MdIdCharStr.asMdId(mdName);
+ MaIdShort maId = MaIdCharStr.asMaId(maName);
+ MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get();
+ MaintenanceAssociation ma = get(CfmMdService.class)
+ .getMaintenanceAssociation(mdId, maId).get();
+
+ MepId mepId = MepId.valueOf(mepIdShort);
+
+ try {
+ get(CfmMepService.class).abortLoopback(md.mdId(), ma.maId(), mepId);
+ } catch (CfmConfigException e) {
+ log.error("Abort Loopback on " + mdName + "/" + maName +
+ "/{} failed", String.valueOf(mepIdShort), e);
+ return Response.serverError()
+ .entity("{ \"failure\":\"" + e.toString() + "\" }")
+ .build();
+ }
+
+ return Response.accepted()
+ .entity("{ \"success\":\"Loopback on MEP " + mdName + "/" + ma.maId() + "/"
+ + mepId.id() + " aborted\" }").build();
+ }
+
+ /**
+ * Transmit Linktrace on MEP with MD name, MA name and Mep Id.
+ *
+ * @param mdName The name of a Maintenance Domain
+ * @param maName The name of a Maintenance Association belonging to the MD
+ * @param mepIdShort The id of a MEP belonging to the MA
+ * @param input A JSON formatted input stream specifying the Linktrace parameters
+ * @return 202 Received with success message or 500 on error
+ */
+ @PUT
+ @Path("{mep_id}/transmit-linktrace")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response transmitLinktrace(
+ @PathParam("md_name") String mdName,
+ @PathParam("ma_name") String maName,
+ @PathParam("mep_id") short mepIdShort,
+ InputStream input) {
+ log.debug("PUT called to Transmit Linktrace on Mep");
+
+ MdId mdId = MdIdCharStr.asMdId(mdName);
+ MaIdShort maId = MaIdCharStr.asMaId(maName);
+ MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get();
+ MaintenanceAssociation ma = get(CfmMdService.class)
+ .getMaintenanceAssociation(mdId, maId).get();
+
+ MepId mepId = MepId.valueOf(mepIdShort);
+
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode cfg = mapper.readTree(input);
+ JsonCodec<MepLtCreate> mepLtCreateCodec = codec(MepLtCreate.class);
+
+ MepLtCreate ltCreate = mepLtCreateCodec.decode((ObjectNode) cfg, this);
+ get(CfmMepService.class).transmitLinktrace(md.mdId(), ma.maId(), mepId, ltCreate);
+ } catch (Exception | CfmConfigException e) {
+ log.error("Transmit Linktrace on " + mdName + "/" + maName +
+ "/{} failed", String.valueOf(mepIdShort), e);
+ return Response.serverError()
+ .entity("{ \"failure\":\"" + e.toString() + "\" }")
+ .build();
+ }
+
+ return Response.accepted()
+ .entity("{ \"success\":\"Linktrace on MEP " + mdName + "/" + ma.maId() + "/"
+ + mepId.id() + " started\" }").build();
+ }
+}