Implemented the following PW features and fixes:
- PW support for H-AGG topologies. Support for leaf-spine-spine
leaf-spine-spine-leaf pseudowires.
- Renamed pw commands with sr-pw-* pattern and also removed redundant output
from them.
- Enabled bulk addition / removal of pws from the rest api.
- Modified diagnostics tool with the updated command name.
Change-Id: I708db9281d0082b160cbd713910b420ef7df9da3
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
index f2fe786..fba6ff9 100644
--- a/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
@@ -78,7 +78,7 @@
* @param json Json to decode.
* @return The pseudowire id.
*/
- public Integer decodeId(ObjectNode json) {
+ public static Integer decodeId(ObjectNode json) {
Integer id = parsePwId(json.path(PW_ID).asText());
if (id == null) {
diff --git a/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
index ba151a1..1a71346 100644
--- a/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
+++ b/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
@@ -15,8 +15,11 @@
*/
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;
@@ -36,9 +39,12 @@
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.
*/
@@ -46,6 +52,8 @@
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);
@@ -107,7 +115,7 @@
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
}
- log.info("Creating pseudowire {} from rest api!", pseudowire.l2Tunnel().tunnelId());
+ log.debug("Creating pseudowire {} from rest api!", pseudowire.l2Tunnel().tunnelId());
L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
switch (res) {
@@ -118,7 +126,50 @@
return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build();
case SUCCESS:
- log.info("Pseudowire {} succesfully deployed!", pseudowire.l2Tunnel().tunnelId());
+ 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();
@@ -146,7 +197,7 @@
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
}
- log.info("Deleting pseudowire {} from rest api!", pseudowireId);
+ log.debug("Deleting pseudowire {} from rest api!", pseudowireId);
L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
switch (res) {
@@ -157,10 +208,64 @@
return Response.noContent().build();
case SUCCESS:
- log.info("Pseudowire {} was removed succesfully!", pseudowireId);
+ 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();
+ }
}
diff --git a/web/src/main/resources/definitions/PseudowireCreateBulk.json b/web/src/main/resources/definitions/PseudowireCreateBulk.json
new file mode 100644
index 0000000..44db619
--- /dev/null
+++ b/web/src/main/resources/definitions/PseudowireCreateBulk.json
@@ -0,0 +1,66 @@
+{
+ "type": "object",
+ "title": "pseudowire-creation-bulk",
+ "required": [
+ "pseudowires"
+ ],
+ "properties": {
+ "pseudowires": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "pwId": {
+ "type": "string",
+ "example": "42",
+ "description": "Id of pseudowire to create."
+ },
+ "cP1": {
+ "type": "string",
+ "example": "of:0000000000000227/25",
+ "description": "Pseudowire connection point 1."
+ },
+ "cP2": {
+ "type": "string",
+ "example": "of:0000000000000226/25",
+ "description": "Pseudowire connection point 2."
+ },
+ "cP1InnerTag": {
+ "type": "string",
+ "example": "101",
+ "description": "Inner vlan for pseudowire connection point 1."
+ },
+ "cP1OuterTag": {
+ "type": "string",
+ "example": "",
+ "description": "Outer vlan for pseudowire connection point 1."
+ },
+ "cP2InnerTag": {
+ "type": "string",
+ "example": "101",
+ "description": "Inner vlan for pseudowire connection point 2."
+ },
+ "cP2OuterTag": {
+ "type": "string",
+ "example": "",
+ "description": "Outer vlan for pseudowire connection point 2."
+ },
+ "mode": {
+ "type": "string",
+ "example": "RAW",
+ "description": "Working mode of pseudowire."
+ },
+ "sDTag": {
+ "type": "string",
+ "example": "",
+ "description": "Service delimiting tag of the pseudowire"
+ },
+ "pwLabel": {
+ "type": "256",
+ "example": "",
+ "description": "Pseudowire label."
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/src/main/resources/definitions/PseudowireDeleteBulk.json b/web/src/main/resources/definitions/PseudowireDeleteBulk.json
new file mode 100644
index 0000000..2edc7e6
--- /dev/null
+++ b/web/src/main/resources/definitions/PseudowireDeleteBulk.json
@@ -0,0 +1,26 @@
+{
+ "type": "object",
+ "title": "pseudowire-deletion-bulk",
+ "required": [
+ "pseudowires"
+ ],
+ "properties": {
+ "pseudowires": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "title": "pseudowire-1",
+ "required": [
+ "pwId"
+ ],
+ "properties": {
+ "pwId": {
+ "type": "string",
+ "example": "42",
+ "description": "Id of pseudowire to Delete."
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file