Various pseudowire fixes and improvements.
- Co-ordination when creating - removing pseudowires from
different instances with a use of a DistributedLock.
- Fixed REST API To return json with specific error for
the single pw instantiation.
- Fixed REST API to return specific error also for pseudowires
that could not be decoded.
- Minor bug fix to return appropriate error when instantiating
a pw from the command line that could not be decoded.
- Fixed bug when creating spine-leaf-leaf pseudowire where we observed flows in pending state.
- Improved logging.
Change-Id: I60dd0ebf8af63ca74d18cfe4801d01846641fb7b
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
index 00d20a7..8abfa71 100644
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
+++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.segmentrouting.web;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.tuple.Pair;
@@ -27,9 +28,11 @@
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.L2Mode;
+import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
import java.util.List;
import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
@@ -69,13 +72,11 @@
result.put(CP1_INNER_TAG, pseudowire.l2TunnelPolicy().cP1InnerTag().toString());
result.put(CP1_OUTER_TAG, pseudowire.l2TunnelPolicy().cP1OuterTag().toString());
-
-
result.put(CP2_INNER_TAG, pseudowire.l2TunnelPolicy().cP2InnerTag().toString());
result.put(CP2_OUTER_TAG, pseudowire.l2TunnelPolicy().cP2OuterTag().toString());
+ result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
result.put(MODE, pseudowire.l2Tunnel().pwMode() == L2Mode.RAW ? "RAW" : "TAGGED");
- result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
result.put(PW_LABEL, pseudowire.l2Tunnel().pwLabel().toString());
return result;
@@ -101,25 +102,77 @@
}
/**
- * Returns a JSON containing the failed pseudowires and the reason that its one failed.
+ * Encoded in an Object Node the undecoed pseudowire and the specificError it failed.
+ *
+ * @param failedPW The failed pseudowire in json format
+ * @param specificError The specificError it failed
+ * @param context Our context
+ * @return A node containing the information we provided
+ */
+ public ObjectNode encodeError(JsonNode failedPW, String specificError,
+ CodecContext context) {
+ ObjectNode result = context.mapper().createObjectNode();
+
+ result.set(FAILED_PW, failedPW);
+ result.put(REASON, specificError);
+
+ return result;
+ }
+
+ /**
+ * Returns a JSON containing the failed pseudowires and the reason that they failed.
*
* @param failedPws Pairs of pws and reasons.
+ * @param undecodedPws Pairs of pws that we could not decode with reason being illegal arguments.
* @param context The context
* @return ObjectNode representing the json to return
*/
public ObjectNode encodeFailedPseudowires(
List<Pair<DefaultL2TunnelDescription, String>> failedPws,
+ List<Pair<JsonNode, String>> undecodedPws,
CodecContext context) {
ArrayNode failedNodes = context.mapper().createArrayNode();
failedPws.stream()
.forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
+ undecodedPws.stream()
+ .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
final ObjectNode toReturn = context.mapper().createObjectNode();
toReturn.set(FAILED_PWS, failedNodes);
return toReturn;
}
/**
+ *
+ * @param json The json containing the pseudowires.
+ * @param context The context
+ * @return A pair of lists.
+ * First list contains pseudowires that we were not able to decode
+ * along with the reason we could not decode them.
+ * Second list contains successfully decoded pseudowires which we are
+ * going to instantiate.
+ */
+ public Pair<List<Pair<JsonNode, String>>, List<L2TunnelDescription>> decodePws(ArrayNode json,
+ CodecContext context) {
+
+ List<L2TunnelDescription> decodedPws = new ArrayList<>();
+ List<Pair<JsonNode, String>> notDecodedPws = new ArrayList<>();
+ for (JsonNode node : json) {
+ DefaultL2TunnelDescription l2Description;
+ try {
+ l2Description = decode((ObjectNode) node, context);
+ decodedPws.add(l2Description);
+ } catch (IllegalArgumentException e) {
+ // the reason why we could not decode this pseudowire is encoded in the
+ // exception, we need to store it now
+ notDecodedPws.add(Pair.of(node, e.getMessage()));
+ }
+ }
+
+ return Pair.of(notDecodedPws, decodedPws);
+ }
+
+ /**
* Decodes a json containg a single field with the pseudowire id.
*
* @param json Json to decode.
@@ -127,8 +180,10 @@
*/
public static Integer decodeId(ObjectNode json) {
- Integer id = parsePwId(json.path(PW_ID).asText());
- if (id == null) {
+ Integer id;
+ try {
+ id = parsePwId(json.path(PW_ID).asText());
+ } catch (IllegalArgumentException e) {
log.error("Pseudowire id is not an integer!");
return null;
}
@@ -139,66 +194,25 @@
@Override
public DefaultL2TunnelDescription decode(ObjectNode json, CodecContext context) {
- String tempString;
-
Integer id = parsePwId(json.path(PW_ID).asText());
- if (id == null) {
- log.error("Pseudowire id is not an integer");
- return null;
- }
ConnectPoint cP1, cP2;
- try {
- tempString = json.path(CP1).asText();
- cP1 = ConnectPoint.deviceConnectPoint(tempString);
- } catch (Exception e) {
- log.error("cP1 is not a valid connect point!");
- return null;
- }
+ cP1 = ConnectPoint.deviceConnectPoint(json.path(CP1).asText());
+ cP2 = ConnectPoint.deviceConnectPoint(json.path(CP2).asText());
- try {
- tempString = json.path(CP2).asText();
- cP2 = ConnectPoint.deviceConnectPoint(tempString);
- } catch (Exception e) {
- log.error("cP2 is not a valid connect point!");
- return null;
- }
-
- VlanId cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText());
- VlanId cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText());
- VlanId cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText());
- VlanId cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText());
- if ((cP1InnerVlan == null) || (cP1OuterVlan == null) ||
- (cP2InnerVlan == null) || (cP2OuterVlan == null)) {
- log.error("One or more vlan for cp1 or cp2 is malformed, it shouldbe an integer / Any / None / *");
- return null;
- }
+ VlanId cP1InnerVlan, cP1OuterVlan, cP2InnerVlan, cP2OuterVlan, sdTag;
+ cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText());
+ cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText());
+ cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText());
+ cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText());
+ sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText());
L2Mode mode = parseMode(json.path(MODE).asText());
- if (mode == null) {
- log.error("Mode should be RAW or TAGGED!");
- return null;
- }
-
- VlanId sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText());
- if (sdTag == null) {
- log.error("SD tag is malformed, it should be an integer / Any / None / *");
- return null;
- }
-
MplsLabel pwLabel = parsePWLabel(json.path(PW_LABEL).asText());
- if (pwLabel == null) {
- log.error("PW label is malformed, should be an integer!");
- return null;
- }
- DefaultL2Tunnel l2Tunnel;
- DefaultL2TunnelPolicy l2Policy;
-
- l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel);
- l2Policy = new DefaultL2TunnelPolicy(id, cP1, cP1InnerVlan, cP1OuterVlan,
+ DefaultL2Tunnel l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel);
+ DefaultL2TunnelPolicy l2Policy = new DefaultL2TunnelPolicy(id, cP1, cP1InnerVlan, cP1OuterVlan,
cP2, cP2InnerVlan, cP2OuterVlan);
-
return new DefaultL2TunnelDescription(l2Tunnel, l2Policy);
}