blob: 1a713466fc8a8c127593ec8e071109b122cbedee [file] [log] [blame]
/*
* Copyright 2015-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.segmentrouting.web;
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;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.segmentrouting.SegmentRoutingService;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.L2Tunnel;
import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Query, create and remove pseudowires.
*/
@Path("pseudowire")
public class PseudowireWebResource extends AbstractWebResource {
private static final PseudowireCodec PSEUDOWIRE_CODEC = new PseudowireCodec();
public static final String PWS = "pseudowires";
private static final String PWS_KEY_ERROR = "Pseudowires key must be present.";
private static Logger log = LoggerFactory
.getLogger(PseudowireWebResource.class);
/**
* Get all pseudowires.
* Returns an array of pseudowires.
*
* @return status of OK
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getPseudowire() {
SegmentRoutingService srService = get(SegmentRoutingService.class);
log.debug("Fetching pseudowires form rest api!");
List<L2TunnelPolicy> policies = srService.getL2Policies();
List<L2Tunnel> tunnels = srService.getL2Tunnels();
List<DefaultL2TunnelDescription> pseudowires = tunnels.stream()
.map(l2Tunnel -> {
L2TunnelPolicy policy = null;
for (L2TunnelPolicy l2Policy : policies) {
if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
policy = l2Policy;
break;
}
}
// return a copy
return new DefaultL2TunnelDescription(l2Tunnel, policy);
})
.collect(Collectors.toList());
ObjectNode result = new ObjectMapper().createObjectNode();
result.set("pseudowires", new PseudowireCodec().encode(pseudowires, this));
return ok(result.toString()).build();
}
/**
* Create a new pseudowire.
*
* @param input JSON stream for pseudowire to create
* @return Response with appropriate status
* @throws IOException Throws IO exception.
* @onos.rsModel PseudowireCreate
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createPseudowire(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ObjectNode pseudowireJson = (ObjectNode) mapper.readTree(input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
DefaultL2TunnelDescription pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
if (pseudowire == null) {
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
}
log.debug("Creating pseudowire {} from rest api!", pseudowire.l2Tunnel().tunnelId());
L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
switch (res) {
case ADDITION_ERROR:
log.error("Pseudowire {} could not be added, error in configuration," +
" please check logs for more details!",
pseudowire.l2Tunnel().tunnelId());
return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build();
case SUCCESS:
log.debug("Pseudowire {} succesfully deployed!", pseudowire.l2Tunnel().tunnelId());
return Response.ok().build();
default:
return Response.ok().build();
}
}
/**
* Create a bulk of pseudowires.
*
* @param input JSON stream for pseudowires to create
* @return Response with appropriate status
* @throws IOException Throws IO exception.
* @onos.rsModel PseudowireCreateBulk
*/
@POST
@Path("/bulk")
@Consumes(MediaType.APPLICATION_JSON)
public Response createPseudowiresBulk(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ObjectNode pseudowireJson = (ObjectNode) mapper.readTree(input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
List<DefaultL2TunnelDescription> pseudowires;
try {
ArrayNode pseudowiresArray = nullIsIllegal((ArrayNode) pseudowireJson.get(PWS), PWS_KEY_ERROR);
pseudowires = PSEUDOWIRE_CODEC.decode(pseudowiresArray, this);
} catch (ItemNotFoundException e) {
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
}
log.debug("Creating pseudowires {} from rest api!", pseudowires);
L2TunnelHandler.Result res = srService.addPseudowiresBulk(pseudowires);
switch (res) {
case ADDITION_ERROR:
log.error("Bulk of pseudowires {} could not be added, error in configuration," +
" please check logs for more details!",
pseudowires);
return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build();
case SUCCESS:
log.debug("Bulk of pseudowires {} succesfully deployed!", pseudowires);
return Response.ok().build();
default:
return Response.ok().build();
}
}
/**
* Delete a pseudowire.
*
* @param input JSON stream for pseudowire to delete
* @return Response with appropriate status
* @throws IOException Throws IO exception.
* @onos.rsModel PseudowireDelete
*/
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
public Response removePseudowire(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ObjectNode pseudowireJson = (ObjectNode) mapper.readTree(input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
Integer pseudowireId = PSEUDOWIRE_CODEC.decodeId(pseudowireJson);
if (pseudowireId == null) {
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
}
log.debug("Deleting pseudowire {} from rest api!", pseudowireId);
L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
switch (res) {
case REMOVAL_ERROR:
log.error("Pseudowire {} could not be removed, error in configuration," +
" please check logs for more details!",
pseudowireId);
return Response.noContent().build();
case SUCCESS:
log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
return Response.noContent().build();
default:
return Response.noContent().build();
}
}
/**
* Delete a bulk of pseudowires.
*
* @param input JSON stream for pseudowires to delete
* @return Response with appropriate status
* @throws IOException Throws IO exception.
* @onos.rsModel PseudowireDeleteBulk
*/
@DELETE
@Path("/bulk")
@Consumes(MediaType.APPLICATION_JSON)
public Response removePseudowiresBulk(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ObjectNode pseudowireJson = (ObjectNode) mapper.readTree(input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
List<Integer> ids = new ArrayList<>();
// try to parse all ids, if key is not present, or if an id is not an int
// throw an exception and stop process
try {
for (JsonNode node : pseudowireJson.withArray(PWS)) {
Integer idToDelete = PseudowireCodec.decodeId((ObjectNode) node);
if (idToDelete == null) {
log.error("Error when parsing pseudowire for deletion in REST API.");
throw new IllegalArgumentException("Id of pseudowire should be an integer!");
}
ids.add(idToDelete);
}
} catch (IllegalArgumentException e) {
log.error("Pseudowire ID should be an integer.");
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
} catch (UnsupportedOperationException e) {
log.error("Pseudowires for deletion should be an array of pseudowire ids.");
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
}
for (Integer pseudowireId : ids) {
L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
switch (res) {
case REMOVAL_ERROR:
log.error("Pseudowire {} could not be removed, error in configuration," +
" please check logs for more details!",
pseudowireId);
case SUCCESS:
log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
default:
}
}
return Response.noContent().build();
}
}