Bug-2234: Propagate PCEP errors via RPC 84/12184/2
authorMilos Fabian <milfabia@cisco.com>
Thu, 23 Oct 2014 07:03:59 +0000 (09:03 +0200)
committerMilos Fabian <milfabia@cisco.com>
Thu, 23 Oct 2014 09:32:07 +0000 (09:32 +0000)
-errors are added also in case the error was detected before request was sent

-add-lsp:
-"SYMBOLIC-PATH-NAME in use" if such LSP already exists
-"Capability not supported" if PCE does not have initiate capability
-update-lsp:
-"unknown PLSP-ID" if such LSP does not exist
-remove-lsp:
-"unknown PLSP-ID" if such LSP does not exist

Change-Id: Icb7096ef4bcfc5383751993fcc588168895a1ca6
Signed-off-by: Milos Fabian <milfabia@cisco.com>
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/OperationResults.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/Stateful02TopologySessionListener.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/Stateful07TopologySessionListener.java
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/Stateful07TopologySessionListenerTest.java

index 65a8002830fb234f5a6ec2d62971fd75666d715e..fc424dfddc45b36551278eda6098ca39b78a7db7 100644 (file)
@@ -11,11 +11,12 @@ import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-
 import java.util.Collections;
 import java.util.List;
-
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObjectBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.Errors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.ErrorsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.FailureType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.operation.result.Error;
@@ -45,8 +46,8 @@ final class OperationResults implements OperationResult {
         this.error = null;
     }
 
-    private OperationResults(final List<Error> error) {
-        this.failure = FailureType.Failed;
+    private OperationResults(final FailureType failure, final List<Error> error) {
+        this.failure = failure;
         this.error = error;
     }
 
@@ -56,7 +57,18 @@ final class OperationResults implements OperationResult {
 
     public static OperationResults createFailed(final List<Errors> errors) {
         final List<Errors> e = errors != null ? errors : Collections.<Errors>emptyList();
-        return new OperationResults(Lists.transform(e, CONVERT_ERRORS));
+        return new OperationResults(FailureType.Failed, Lists.transform(e, CONVERT_ERRORS));
+    }
+
+    public static OperationResults createUnsent(final PCEPErrors error) {
+        final List<Errors> e = error != null ? Collections.singletonList(getErrorFor(error)) : Collections.<Errors>emptyList();
+        return new OperationResults(FailureType.Unsent, Lists.transform(e, CONVERT_ERRORS));
+    }
+
+    private static Errors getErrorFor(final PCEPErrors error) {
+        final ErrorsBuilder builder = new ErrorsBuilder();
+        builder.setErrorObject(new ErrorObjectBuilder().setType(error.getErrorType()).setValue(error.getErrorValue()).build());
+        return builder.build();
     }
 
     @Override
index fb9542ec1fe3e1787e4ebfb8ca97e345f8826498..554aeee6767a77bb04eabd51fbc9cc34c58a54dd 100644 (file)
@@ -19,6 +19,7 @@ import java.nio.ByteBuffer;
 import java.util.Collections;
 import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
 import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.PcinitiateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.Stateful1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.pcinitiate.message.PcinitiateMessageBuilder;
@@ -166,7 +167,7 @@ public class Stateful02TopologySessionListener extends AbstractTopologySessionLi
             public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
                 if (rep.isPresent()) {
                     LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
-                    return OperationResults.UNSENT.future();
+                    return OperationResults.createUnsent(PCEPErrors.USED_SYMBOLIC_PATH_NAME).future();
                 }
 
                 final SymbolicPathNameBuilder name = new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(input.getName().getBytes(Charsets.UTF_8)));
@@ -203,7 +204,7 @@ public class Stateful02TopologySessionListener extends AbstractTopologySessionLi
                 final Lsp reportedLsp = validateReportedLsp(rep, input);
                 if (reportedLsp == null) {
                     LOG.warn("Reported LSP does not contain LSP object.");
-                    return OperationResults.UNSENT.future();
+                    return OperationResults.createUnsent(PCEPErrors.UNKNOWN_PLSP_ID).future();
                 }
                 // Build the request and send it
                 final UpdatesBuilder rb = new UpdatesBuilder();
@@ -227,7 +228,7 @@ public class Stateful02TopologySessionListener extends AbstractTopologySessionLi
             public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
                 final Lsp reportedLsp = validateReportedLsp(rep, input);
                 if (reportedLsp == null) {
-                    return OperationResults.UNSENT.future();
+                    return OperationResults.createUnsent(PCEPErrors.UNKNOWN_PLSP_ID).future();
                 }
                 final Arguments2 args = input.getArguments().getAugmentation(Arguments2.class);
                 Preconditions.checkArgument(args != null, "Input is missing operational tag.");
index 1fa30d9f1c4197c861257433cf7b7317a4de3ad9..2689201a7f8d0d93456980ac54fd02289b67ae6a 100644 (file)
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
 import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
@@ -224,10 +225,10 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
             public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
                 if (rep.isPresent()) {
                     LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
-                    return OperationResults.UNSENT.future();
+                    return OperationResults.createUnsent(PCEPErrors.USED_SYMBOLIC_PATH_NAME).future();
                 }
                 if (!getPeerCapabilities().getInstantiation()) {
-                    return OperationResults.UNSENT.future();
+                    return OperationResults.createUnsent(PCEPErrors.CAPABILITY_NOT_SUPPORTED).future();
                 }
 
                 // Build the request
@@ -273,7 +274,7 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
             public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
                 final Lsp reportedLsp = validateReportedLsp(rep, input);
                 if (reportedLsp == null) {
-                    return OperationResults.UNSENT.future();
+                    return OperationResults.createUnsent(PCEPErrors.UNKNOWN_PLSP_ID).future();
                 }
                 // Build the request and send it
                 final RequestsBuilder rb = new RequestsBuilder();
@@ -300,7 +301,7 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
             public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
                 final Lsp reportedLsp = validateReportedLsp(rep, input);
                 if (reportedLsp == null) {
-                    return OperationResults.UNSENT.future();
+                    return OperationResults.createUnsent(PCEPErrors.UNKNOWN_PLSP_ID).future();
                 }
                 // create mandatory objects
                 final Srp srp = new SrpBuilder().setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE).build();
index e1e365c0c0c3e1aa4965494c8513b41e99e75bc4..2e47d1561034d2961036530c62100345f3d922f1 100644 (file)
@@ -85,6 +85,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.add.lsp.args.ArgumentsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsp;
@@ -311,6 +312,57 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
         assertFalse(topology.getNode().isEmpty());
     }
 
+    @Test
+    public void testUpdateUnknownLsp() throws InterruptedException, ExecutionException {
+        this.listener.onSessionUp(this.session);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder updArgsBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder();
+        updArgsBuilder.setEro(createEroWithIpPrefixes(Lists.newArrayList(ERO_IP_PREFIX, DST_IP_PREFIX)));
+        updArgsBuilder.addAugmentation(Arguments3.class, new Arguments3Builder().setLsp(new LspBuilder().setDelegate(true).setAdministrative(true).build()).build());
+        final UpdateLspInput update = new UpdateLspInputBuilder().setArguments(updArgsBuilder.build()).setName(TUNNEL_NAME).setNetworkTopologyRef(new NetworkTopologyRef(TOPO_IID)).setNode(NODE_ID).build();
+        final UpdateLspOutput result = this.topologyRpcs.updateLsp(update).get().getResult();
+        assertEquals(FailureType.Unsent, result.getFailure());
+        assertEquals(1, result.getError().size());
+        final ErrorObject errorObject = result.getError().get(0).getErrorObject();
+        assertNotNull(errorObject);
+        assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, PCEPErrors.forValue(errorObject.getType(), errorObject.getValue()));
+    }
+
+    @Test
+    public void testRemoveUnknownLsp() throws InterruptedException, ExecutionException {
+        this.listener.onSessionUp(this.session);
+        final RemoveLspInput remove = new RemoveLspInputBuilder().setName(TUNNEL_NAME).setNetworkTopologyRef(new NetworkTopologyRef(TOPO_IID)).setNode(NODE_ID).build();
+        final OperationResult result = this.topologyRpcs.removeLsp(remove).get().getResult();
+        assertEquals(FailureType.Unsent, result.getFailure());
+        assertEquals(1, result.getError().size());
+        final ErrorObject errorObject = result.getError().get(0).getErrorObject();
+        assertNotNull(errorObject);
+        assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, PCEPErrors.forValue(errorObject.getType(), errorObject.getValue()));
+    }
+
+    @Test
+    public void testAddAlreadyExistingLsp() throws UnknownHostException, InterruptedException, ExecutionException {
+        this.listener.onSessionUp(this.session);
+        this.topologyRpcs.addLsp(createAddLspInput());
+        assertEquals(1, this.receivedMsgs.size());
+        assertTrue(this.receivedMsgs.get(0) instanceof Pcinitiate);
+        final Pcinitiate pcinitiate = (Pcinitiate) this.receivedMsgs.get(0);
+        final Requests req = pcinitiate.getPcinitiateMessage().getRequests().get(0);
+        final long srpId = req.getSrp().getOperationId().getValue();
+        final InetAddress inetAddress = InetAddress.getByName(TEST_ADDRESS);
+        final Tlvs tlvs = createLspTlvs(req.getLsp().getPlspId().getValue(), true,
+                inetAddress, inetAddress, inetAddress);
+        final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs).setPlspId(new PlspId(1L)).setSync(false).setRemove(false).setOperational(OperationalStatus.Active).build(), Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(req.getEro().getSubobject()));
+        this.listener.onMessage(this.session, pcRpt);
+
+        //try to add already existing LSP
+        final AddLspOutput result = this.topologyRpcs.addLsp(createAddLspInput()).get().getResult();
+        assertEquals(FailureType.Unsent, result.getFailure());
+        assertEquals(1, result.getError().size());
+        final ErrorObject errorObject = result.getError().get(0).getErrorObject();
+        assertNotNull(errorObject);
+        assertEquals(PCEPErrors.USED_SYMBOLIC_PATH_NAME, PCEPErrors.forValue(errorObject.getType(), errorObject.getValue()));
+    }
+
     @Override
     protected Open getLocalPref() {
         return new OpenBuilder(super.getLocalPref()).setTlvs(new TlvsBuilder().addAugmentation(Tlvs1.class, new Tlvs1Builder().setStateful(new StatefulBuilder().addAugmentation(Stateful1.class, new Stateful1Builder().setInitiation(Boolean.TRUE).build()).build()).build()).build()).build();