BUG-48: split the programming and immediate parts 39/2439/1
authorRobert Varga <rovarga@cisco.com>
Wed, 6 Nov 2013 11:29:00 +0000 (12:29 +0100)
committerRobert Varga <rovarga@cisco.com>
Wed, 6 Nov 2013 12:33:16 +0000 (13:33 +0100)
Change-Id: I1b88f63f3a0c8b64516addaa774454077c5cf6c3
Signed-off-by: Robert Varga <rovarga@cisco.com>
pcep/topology-api/src/main/yang/network-topology-pcep-programming.yang [new file with mode: 0644]
pcep/topology-api/src/main/yang/network-topology-pcep.yang
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/BundleActivator.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/PCEPTopologyProvider.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyProgramming.java [new file with mode: 0644]
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyRPCs.java [new file with mode: 0644]

diff --git a/pcep/topology-api/src/main/yang/network-topology-pcep-programming.yang b/pcep/topology-api/src/main/yang/network-topology-pcep-programming.yang
new file mode 100644 (file)
index 0000000..27144c0
--- /dev/null
@@ -0,0 +1,65 @@
+module network-topology-pcep-progrogramming {
+       // vi: set et smarttab sw=4 tabstop=4:
+       yang-version 1;
+       namespace "urn:opendaylight:params:xml:ns:yang:topology:pcep:programming";
+       prefix "pnp";
+
+       import network-topology-programming { prefix ntp; revision-date 2013-11-02; }
+    import network-topology-pcep { prefix pcep; revision-date 2013-10-24; }
+
+       organization "Cisco Systems, Inc.";
+       contact "Robert Varga <rovarga@cisco.com>";
+
+       description
+               "This module contains the PCEP extensions to base topology model. It
+        exposes the LSPs for which a particular node is the head end.
+
+        This module exposes three programming instructions,add-lsp,
+        remove-lsp and update-lsp, which map to actively-stateful PCEP
+        operations using PCInitiate and PCUpd messages to initiate,
+        destroy and udpate LSP configuration. The lifecycle of these
+        instructions follows draft-crabbe-pce-pce-initiated-lsp and
+        draft-ietf-pce-stateful-pce, completing execution once the head-end
+        router has acknowledged operation success. Should the router become
+        disconnected, the instruction resolve to Cancelled if the message
+        has not been sent into the TCP socket, or Failed it they have.
+
+               Copyright (c)2013 Cisco Systems, Inc. All rights reserved.";
+
+       revision "2013-11-06" {
+               description
+                       "Initial revision.";
+               reference "";
+       }
+
+    rpc submit-add-lsp {
+        input {
+            uses ntp:topology-instruction-input;
+            uses pcep:add-lsp-args;
+        }
+        output {
+            uses ntp:topology-instruction-output;
+        }
+    }
+
+    rpc submit-remove-lsp {
+        input {
+            uses ntp:topology-instruction-input;
+            uses pcep:remove-lsp-args;
+        }
+        output {
+            uses ntp:topology-instruction-output;
+        }
+    }
+
+    rpc submit-update-lsp {
+        input {
+            uses ntp:topology-instruction-input;
+            uses pcep:update-lsp-args;
+        }
+        output {
+            uses ntp:topology-instruction-output;
+        }
+    }
+}
+
index 390d123692bb54f422bdd2a3fadbe7f9cba98c01..fbeb3cacf64dadaf601ac980351990f7463f1a1e 100644 (file)
@@ -5,7 +5,6 @@ module network-topology-pcep {
        prefix "pn";
 
        import network-topology { prefix nt; revision-date 2013-10-21; }
-       import network-topology-programming { prefix ntp; revision-date 2013-11-02; }
        import pcep-types { prefix pcep; revision-date 2013-10-05; }
 
        organization "Cisco Systems, Inc.";
@@ -96,82 +95,90 @@ module network-topology-pcep {
                uses pcep-client-attributes;
        }
 
-    rpc add-lsp {
-        input {
-            uses ntp:topology-instruction-input;
+    typedef failure-type {
+        type enumeration {
+            enum unsent;
+            enum no-ack;
+            enum failed;
+        }
+    }
 
-            leaf node {
-                type nt:node-ref;
-                mandatory true;
-            }
+    grouping lsp-id {
+        leaf node {
+            type nt:node-ref;
+            mandatory true;
+        }
 
-            leaf name {
-                type pcep:symbolic-path-name;
-                mandatory true;
-            }
+        leaf name {
+            type pcep:symbolic-path-name;
+            mandatory true;
+        }
+    }
 
-            container arguments {
-                leaf administrative {
-                    type boolean;
-                    default true;
-                }
+    grouping operation-result {
+        leaf failure {
+            type failure-type;
+        }
+    }
 
-                               container endpoints {
-                                       uses pcep:endpoints-object;
-                               }
+    grouping add-lsp-args {
+        uses lsp-id;
+
+        container arguments {
+            leaf administrative {
+                type boolean;
+                default true;
+            }
 
-                uses pcep:path-definition;
+            container endpoints {
+                uses pcep:endpoints-object;
             }
+
+            uses pcep:path-definition;
+        }
+    }
+
+    rpc add-lsp {
+        input {
+            uses add-lsp-args;
         }
         output {
-            uses ntp:topology-instruction-output;
+            uses operation-result;
         }
     }
 
+    grouping remove-lsp-args {
+        uses lsp-id;
+    }
+
     rpc remove-lsp {
         input {
-            uses ntp:topology-instruction-input;
-
-            leaf node {
-                type nt:node-ref;
-                mandatory true;
-            }
-
-            leaf name {
-                type pcep:symbolic-path-name;
-                mandatory true;
-            }
+            uses remove-lsp-args;
         }
         output {
-            uses ntp:topology-instruction-output;
+            uses operation-result;
         }
     }
 
-    rpc update-lsp {
-        input {
-            uses ntp:topology-instruction-input;
-
-            leaf node {
-                type nt:node-ref;
-                mandatory true;
-            }
+    grouping update-lsp-args {
+        uses lsp-id;
 
-            leaf name {
-                type pcep:symbolic-path-name;
-                mandatory true;
+        container arguments {
+            leaf administrative {
+                type boolean;
+                default true;
             }
 
-            container arguments {
-                leaf administrative {
-                    type boolean;
-                    default true;
-                }
+            uses pcep:path-definition;
+        }
+    }
 
-                uses pcep:path-definition;
-            }
+    rpc update-lsp {
+        input {
+            uses update-lsp-args;
         }
         output {
-            uses ntp:topology-instruction-output;
+            uses operation-result;
         }
     }
 }
index 21cb7ffa554d34763deb294dd82b8d2b5f4db53d..6ffca6c4f7bb4294a034675616a836bab3e92c8e 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.bgpcep.pcep.topology.provider;
 
 import io.netty.channel.ChannelFuture;
 import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.GlobalEventExecutor;
 
 import java.net.InetSocketAddress;
 import java.util.concurrent.ExecutionException;
@@ -44,7 +45,7 @@ public final class BundleActivator extends AbstractBindingAwareProvider {
                final PCEPDispatcher dispatcher = new PCEPDispatcherImpl(PCEPExtensionProviderContextImpl.getSingletonInstance().getMessageHandlerRegistry(), new DefaultPCEPSessionNegotiatorFactory(new HashedWheelTimer(), prefs, 5));
                final InstanceIdentifier<Topology> topology = InstanceIdentifier.builder().node(Topology.class).toInstance();
 
-               final PCEPTopologyProvider exp = new PCEPTopologyProvider(dispatcher, null, dps, topology);
+               final PCEPTopologyProvider exp = new PCEPTopologyProvider(dispatcher, GlobalEventExecutor.INSTANCE, null, dps, topology);
                final ChannelFuture s = exp.startServer(address);
                try {
                        s.get();
index 527ce41cf5b76d783c7d8dd250ac297cd5b46743..c0cf2c2b413e35041fe8fc261adabbf250248540 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.bgpcep.pcep.topology.provider;
 
 import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.EventExecutor;
 
 import java.net.InetSocketAddress;
 
@@ -21,21 +22,24 @@ import com.google.common.base.Preconditions;
 
 public final class PCEPTopologyProvider {
        private final PCEPDispatcher dispatcher;
-       private final DataProviderService dataProvider;
-       private final InstanceIdentifier<Topology> topology;
-       private final InstructionScheduler scheduler;
+       private final TopologyProgramming topology;
+       private final ServerSessionManager manager;
+       private final TopologyRPCs element;
 
        public PCEPTopologyProvider(final PCEPDispatcher dispatcher,
+                       final EventExecutor executor,
                        final InstructionScheduler scheduler,
                        final DataProviderService dataService,
                        final InstanceIdentifier<Topology> topology) {
                this.dispatcher = Preconditions.checkNotNull(dispatcher);
-               this.dataProvider = Preconditions.checkNotNull(dataService);
-               this.topology = Preconditions.checkNotNull(topology);
-               this.scheduler = Preconditions.checkNotNull(scheduler);
+
+
+               this.manager = new ServerSessionManager(executor, dataService, topology);
+               this.element = new TopologyRPCs(executor, manager);
+               this.topology = new TopologyProgramming(executor, scheduler, manager);
        }
 
        public ChannelFuture startServer(final InetSocketAddress address) {
-               return dispatcher.createServer(address, new ServerSessionManager(scheduler, dataProvider, topology));
+               return dispatcher.createServer(address, manager);
        }
 }
index c04fe911e3bcf095d20ebf4b9e8917c2b2c54dae..7fd43de770899b3354c8265ba700f01368ed2b8a 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.bgpcep.pcep.topology.provider;
 
 import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.FutureListener;
-import io.netty.util.concurrent.GlobalEventExecutor;
 import io.netty.util.concurrent.Promise;
 
 import java.net.InetAddress;
@@ -21,10 +20,6 @@ import java.util.concurrent.Future;
 
 import javax.annotation.concurrent.GuardedBy;
 
-import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
-import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
-import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
-import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
@@ -60,23 +55,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.typ
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.stateful.capability.tlv.Stateful;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.symbolic.path.name.tlv.SymbolicPathName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.symbolic.path.name.tlv.SymbolicPathNameBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.FailureBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.Failure;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
+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.Node1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1Builder;
+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.PccSyncState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutputBuilder;
-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.UpdateLspOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClientBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLspsKey;
@@ -98,14 +84,14 @@ import com.google.common.collect.ImmutableList;
 /**
  *
  */
-final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, NetworkTopologyPcepService {
+final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener> {
        private static String createNodeId(final InetAddress addr) {
                return "pcc://" + addr.getHostAddress();
        }
 
        private final class SessionListener implements PCEPSessionListener {
-               private final Map<SrpIdNumber, Promise<ExecutionResult<Details>>> waitingRequests = new HashMap<>();
-               private final Map<SrpIdNumber, Promise<ExecutionResult<Details>>> sendingRequests = new HashMap<>();
+               private final Map<SrpIdNumber, Promise<OperationResult>> waitingRequests = new HashMap<>();
+               private final Map<SrpIdNumber, Promise<OperationResult>> sendingRequests = new HashMap<>();
                private final Map<PlspId, SymbolicPathName> lsps = new HashMap<>();
                private PathComputationClientBuilder pccBuilder;
                private InstanceIdentifier<Node1> topologyAugment;
@@ -218,16 +204,16 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                        }
 
                        // Clear all requests which have not been sent to the peer: they result in cancellation
-                       for (final Entry<SrpIdNumber, Promise<ExecutionResult<Details>>> e : this.sendingRequests.entrySet()) {
+                       for (final Entry<SrpIdNumber, Promise<OperationResult>> e : this.sendingRequests.entrySet()) {
                                LOG.debug("Request {} was not sent when session went down, cancelling the instruction", e.getKey());
-                               e.getValue().setSuccess(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                               e.getValue().setSuccess(OPERATION_UNSENT);
                        }
                        this.sendingRequests.clear();
 
                        // CLear all requests which have not been acked by the peer: they result in failure
-                       for (final Entry<SrpIdNumber, Promise<ExecutionResult<Details>>> e : this.waitingRequests.entrySet()) {
+                       for (final Entry<SrpIdNumber, Promise<OperationResult>> e : this.waitingRequests.entrySet()) {
                                LOG.info("Request {} was incomplete when session went down, failing the instruction", e.getKey());
-                               e.getValue().setSuccess(new ExecutionResult<Details>(InstructionStatus.Failed, null));
+                               e.getValue().setSuccess(OPERATION_NOACK);
                        }
                        this.waitingRequests.clear();
                }
@@ -278,10 +264,10 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                                                case Active:
                                                case Down:
                                                case Up:
-                                                       final Promise<ExecutionResult<Details>> p = this.waitingRequests.remove(id);
+                                                       final Promise<OperationResult> p = this.waitingRequests.remove(id);
                                                        if (p != null) {
                                                                LOG.debug("Request {} resulted in LSP operational state {}", id, lsp.getOperational());
-                                                               p.setSuccess(new ExecutionResult<Details>(InstructionStatus.Successful, null));
+                                                               p.setSuccess(OPERATION_SUCCESS);
                                                        } else {
                                                                LOG.warn("Request ID {} not found in outstanding DB", id);
                                                        }
@@ -340,20 +326,20 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                }
 
                private synchronized void messageSendingComplete(final SrpIdNumber requestId, final io.netty.util.concurrent.Future<Void> future) {
-                       final Promise<ExecutionResult<Details>> promise = this.sendingRequests.remove(requestId);
+                       final Promise<OperationResult> promise = this.sendingRequests.remove(requestId);
 
                        if (future.isSuccess()) {
                                this.waitingRequests.put(requestId, promise);
                        } else {
                                LOG.info("Failed to send request {}, instruction cancelled", requestId, future.cause());
-                               promise.setSuccess(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                               promise.setSuccess(OPERATION_UNSENT);
                        }
                }
 
-               private synchronized io.netty.util.concurrent.Future<ExecutionResult<Details>> sendMessage(final Message message,
+               private synchronized io.netty.util.concurrent.Future<OperationResult> sendMessage(final Message message,
                                final SrpIdNumber requestId) {
                        final io.netty.util.concurrent.Future<Void> f = this.session.sendMessage(message);
-                       final Promise<ExecutionResult<Details>> ret = exec.newPromise();
+                       final Promise<OperationResult> ret = exec.newPromise();
 
                        this.sendingRequests.put(requestId, ret);
 
@@ -384,17 +370,23 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                        return this.version;
                }
        };
-       private static final EventExecutor exec = GlobalEventExecutor.INSTANCE;
+
+       private static final OperationResult OPERATION_NOACK = createOperationResult(FailureType.NoAck);
+       private static final OperationResult OPERATION_SUCCESS = createOperationResult(null);
+       private static final OperationResult OPERATION_UNSENT = createOperationResult(FailureType.Unsent);
+
        private final Map<NodeId, SessionListener> nodes = new HashMap<>();
        private final InstanceIdentifier<Topology> topology;
        private final DataProviderService dataProvider;
-       private final InstructionScheduler scheduler;
+       private final EventExecutor exec;
 
-       public ServerSessionManager(final InstructionScheduler scheduler, final DataProviderService dataProvider,
+       public ServerSessionManager(
+                       final EventExecutor exec,
+                       final DataProviderService dataProvider,
                        final InstanceIdentifier<Topology> topology) {
                this.dataProvider = Preconditions.checkNotNull(dataProvider);
                this.topology = Preconditions.checkNotNull(topology);
-               this.scheduler = Preconditions.checkNotNull(scheduler);
+               this.exec = Preconditions.checkNotNull(exec);
        }
 
        @Override
@@ -402,12 +394,12 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                return new SessionListener();
        }
 
-       private synchronized io.netty.util.concurrent.Future<ExecutionResult<Details>> realAddLsp(final AddLspInput input) {
+       synchronized io.netty.util.concurrent.Future<OperationResult> realAddLsp(final AddLspArgs input) {
                // Get the listener corresponding to the node
                final SessionListener l = this.nodes.get(input.getNode());
                if (l == null) {
                        LOG.debug("Session for node {} not found", input.getNode());
-                       return exec.newSucceededFuture(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                       return exec.newSucceededFuture(OPERATION_UNSENT);
                }
 
                // Make sure there is no such LSP
@@ -415,7 +407,7 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                                new ReportedLspsKey(input.getName())).toInstance();
                if (this.dataProvider.readOperationalData(lsp) != null) {
                        LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
-                       return exec.newSucceededFuture(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                       return exec.newSucceededFuture(OPERATION_UNSENT);
                }
 
                // Build the request
@@ -433,12 +425,26 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                return l.sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId());
        }
 
-       private synchronized io.netty.util.concurrent.Future<ExecutionResult<Details>> realRemoveLsp(final RemoveLspInput input) {
+       private static OperationResult createOperationResult(final FailureType type) {
+               return new OperationResult() {
+                       @Override
+                       public Class<? extends DataContainer> getImplementedInterface() {
+                               return OperationResult.class;
+                       }
+
+                       @Override
+                       public FailureType getFailure() {
+                               return type;
+                       }
+               };
+       }
+
+       synchronized io.netty.util.concurrent.Future<OperationResult> realRemoveLsp(final RemoveLspArgs input) {
                // Get the listener corresponding to the node
                final SessionListener l = this.nodes.get(input.getNode());
                if (l == null) {
                        LOG.debug("Session for node {} not found", input.getNode());
-                       return exec.newSucceededFuture(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                       return exec.newSucceededFuture(OPERATION_UNSENT);
                }
 
                // Make sure the LSP exists, we need it for PLSP-ID
@@ -447,7 +453,7 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
                if (rep == null) {
                        LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
-                       return exec.newSucceededFuture(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                       return exec.newSucceededFuture(OPERATION_UNSENT);
                }
 
                // Build the request and send it
@@ -460,12 +466,12 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                return l.sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId());
        }
 
-       private synchronized io.netty.util.concurrent.Future<ExecutionResult<Details>> realUpdateLsp(final UpdateLspInput input) {
+       synchronized io.netty.util.concurrent.Future<OperationResult> realUpdateLsp(final UpdateLspArgs input) {
                // Get the listener corresponding to the node
                final SessionListener l = this.nodes.get(input.getNode());
                if (l == null) {
                        LOG.debug("Session for node {} not found", input.getNode());
-                       return exec.newSucceededFuture(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                       return exec.newSucceededFuture(OPERATION_UNSENT);
                }
 
                // Make sure the LSP exists
@@ -474,7 +480,7 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
                if (rep == null) {
                        LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
-                       return exec.newSucceededFuture(new ExecutionResult<Details>(InstructionStatus.Cancelled, null));
+                       return exec.newSucceededFuture(OPERATION_UNSENT);
                }
 
                // Build the PCUpd request and send it
@@ -487,70 +493,4 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                ub.setUpdates(ImmutableList.of(rb.build()));
                return l.sendMessage(new PcupdBuilder().setPcupdMessage(ub.build()).build(), rb.getSrp().getOperationId());
        }
-
-       @Override
-       public Future<RpcResult<AddLspOutput>> addLsp(final AddLspInput input) {
-               Preconditions.checkArgument(input.getNode() != null);
-               Preconditions.checkArgument(input.getName() != null);
-
-               final InstructionExecutor e = new InstructionExecutor() {
-                       @Override
-                       public io.netty.util.concurrent.Future<ExecutionResult<Details>> execute() {
-                               return realAddLsp(input);
-                       }
-               };
-
-               final Failure f = this.scheduler.submitInstruction(input, e);
-               final AddLspOutputBuilder b = new AddLspOutputBuilder();
-               if (f != null) {
-                       b.setResult(new FailureBuilder().setFailure(f).build());
-               }
-
-               final RpcResult<AddLspOutput> res = SuccessfulRpcResult.create(b.build());
-               return exec.newSucceededFuture(res);
-       }
-
-       @Override
-       public Future<RpcResult<RemoveLspOutput>> removeLsp(final RemoveLspInput input) {
-               Preconditions.checkArgument(input.getNode() != null);
-               Preconditions.checkArgument(input.getName() != null);
-
-               final InstructionExecutor e = new InstructionExecutor() {
-                       @Override
-                       public io.netty.util.concurrent.Future<ExecutionResult<Details>> execute() {
-                               return realRemoveLsp(input);
-                       }
-               };
-
-               final Failure f = this.scheduler.submitInstruction(input, e);
-               final RemoveLspOutputBuilder b = new RemoveLspOutputBuilder();
-               if (f != null) {
-                       b.setResult(new FailureBuilder().setFailure(f).build());
-               }
-
-               final RpcResult<RemoveLspOutput> res = SuccessfulRpcResult.create(b.build());
-               return exec.newSucceededFuture(res);
-       }
-
-       @Override
-       public Future<RpcResult<UpdateLspOutput>> updateLsp(final UpdateLspInput input) {
-               Preconditions.checkArgument(input.getNode() != null);
-               Preconditions.checkArgument(input.getName() != null);
-
-               final InstructionExecutor e = new InstructionExecutor() {
-                       @Override
-                       public io.netty.util.concurrent.Future<ExecutionResult<Details>> execute() {
-                               return realUpdateLsp(input);
-                       }
-               };
-
-               final Failure f = this.scheduler.submitInstruction(input, e);
-               final UpdateLspOutputBuilder b = new UpdateLspOutputBuilder();
-               if (f != null) {
-                       b.setResult(new FailureBuilder().setFailure(f).build());
-               }
-
-               final RpcResult<UpdateLspOutput> res = SuccessfulRpcResult.create(b.build());
-               return exec.newSucceededFuture(res);
-       }
 }
diff --git a/pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyProgramming.java b/pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyProgramming.java
new file mode 100644 (file)
index 0000000..4545378
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.FutureListener;
+import io.netty.util.concurrent.Promise;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
+import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
+import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
+import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.FailureBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.Failure;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.NetworkTopologyPcepProgrogrammingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitAddLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitAddLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitAddLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitRemoveLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspOutputBuilder;
+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.yangtools.yang.common.RpcResult;
+
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ */
+final class TopologyProgramming implements NetworkTopologyPcepProgrogrammingService {
+       private abstract class AbstractInstructionExecutor implements InstructionExecutor {
+
+               protected abstract io.netty.util.concurrent.Future<OperationResult> executeImpl();
+
+               @Override
+               public final io.netty.util.concurrent.Future<ExecutionResult<Details>> execute() {
+                       final Promise<ExecutionResult<Details>> promise = exec.newPromise();
+
+                       executeImpl().addListener(new FutureListener<OperationResult>() {
+                               @Override
+                               public void operationComplete(final io.netty.util.concurrent.Future<OperationResult> future) {
+                                       if (future.isSuccess()) {
+                                               final OperationResult res = future.getNow();
+                                               final FailureType fail = res.getFailure();
+
+                                               final ExecutionResult<Details> result;
+                                               if (fail != null) {
+                                                       switch (fail) {
+                                                       case Failed:
+                                                       case NoAck:
+                                                               result = new ExecutionResult<Details>(InstructionStatus.Failed, null);
+                                                               break;
+                                                       case Unsent:
+                                                               result = new ExecutionResult<Details>(InstructionStatus.Cancelled, null);
+                                                               break;
+                                                       }
+
+                                                       throw new IllegalStateException("Unhandled operation state " + fail);
+                                               } else {
+                                                       result = new ExecutionResult<Details>(InstructionStatus.Successful, null);
+                                               }
+
+                                               promise.setSuccess(result);
+                                       } else {
+                                               promise.setFailure(future.cause());
+                                       }
+                               }
+                       });
+
+                       return promise;
+               }
+       }
+
+       private final InstructionScheduler scheduler;
+       private final ServerSessionManager manager;
+       private final EventExecutor exec;
+
+       TopologyProgramming(final EventExecutor executor, final InstructionScheduler scheduler, final ServerSessionManager manager) {
+               this.scheduler = Preconditions.checkNotNull(scheduler);
+               this.manager = Preconditions.checkNotNull(manager);
+               this.exec = Preconditions.checkNotNull(executor);
+       }
+
+       @Override
+       public Future<RpcResult<SubmitAddLspOutput>> submitAddLsp(final SubmitAddLspInput input) {
+               Preconditions.checkArgument(input.getNode() != null);
+               Preconditions.checkArgument(input.getName() != null);
+
+               final InstructionExecutor e = new AbstractInstructionExecutor() {
+                       @Override
+                       public io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+                               return manager.realAddLsp(input);
+                       }
+               };
+
+               final Failure f = this.scheduler.submitInstruction(input, e);
+               final SubmitAddLspOutputBuilder b = new SubmitAddLspOutputBuilder();
+               if (f != null) {
+                       b.setResult(new FailureBuilder().setFailure(f).build());
+               }
+
+               final RpcResult<SubmitAddLspOutput> res = SuccessfulRpcResult.create(b.build());
+               return exec.newSucceededFuture(res);
+       }
+
+       @Override
+       public Future<RpcResult<SubmitRemoveLspOutput>> submitRemoveLsp(final SubmitRemoveLspInput input) {
+               Preconditions.checkArgument(input.getNode() != null);
+               Preconditions.checkArgument(input.getName() != null);
+
+               final InstructionExecutor e = new AbstractInstructionExecutor() {
+                       @Override
+                       protected io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+                               return manager.realRemoveLsp(input);
+                       }
+               };
+
+               final Failure f = this.scheduler.submitInstruction(input, e);
+               final SubmitRemoveLspOutputBuilder b = new SubmitRemoveLspOutputBuilder();
+               if (f != null) {
+                       b.setResult(new FailureBuilder().setFailure(f).build());
+               }
+
+               final RpcResult<SubmitRemoveLspOutput> res = SuccessfulRpcResult.create(b.build());
+               return exec.newSucceededFuture(res);
+       }
+
+       @Override
+       public Future<RpcResult<SubmitUpdateLspOutput>> submitUpdateLsp(final SubmitUpdateLspInput input) {
+               Preconditions.checkArgument(input.getNode() != null);
+               Preconditions.checkArgument(input.getName() != null);
+
+               final InstructionExecutor e = new AbstractInstructionExecutor() {
+                       @Override
+                       protected io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+                               return manager.realUpdateLsp(input);
+                       }
+               };
+
+               final Failure f = this.scheduler.submitInstruction(input, e);
+               final SubmitUpdateLspOutputBuilder b = new SubmitUpdateLspOutputBuilder();
+               if (f != null) {
+                       b.setResult(new FailureBuilder().setFailure(f).build());
+               }
+
+               final RpcResult<SubmitUpdateLspOutput> res = SuccessfulRpcResult.create(b.build());
+               return exec.newSucceededFuture(res);
+       }
+
+}
diff --git a/pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyRPCs.java b/pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyRPCs.java
new file mode 100644 (file)
index 0000000..96490a9
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.FutureListener;
+import io.netty.util.concurrent.Promise;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
+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.RemoveLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutputBuilder;
+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.UpdateLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutputBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.base.Preconditions;
+
+final class TopologyRPCs implements NetworkTopologyPcepService {
+       private final ServerSessionManager manager;
+       private final EventExecutor exec;
+
+       private abstract class ExecutionResultAdaptor<T> implements FutureListener<OperationResult> {
+               protected final Promise<RpcResult<T>> promise = exec.newPromise();
+
+               protected abstract RpcResult<T> convertResult(OperationResult result);
+
+               @Override
+               public final void operationComplete(final io.netty.util.concurrent.Future<OperationResult> future) {
+                       if (future.isSuccess()) {
+                               promise.setSuccess(convertResult(future.getNow()));
+                       } else {
+                               promise.setFailure(future.cause());
+                       }
+               }
+       }
+
+       TopologyRPCs(final EventExecutor exec, final ServerSessionManager manager) {
+               this.manager = Preconditions.checkNotNull(manager);
+               this.exec = Preconditions.checkNotNull(exec);
+       }
+
+       @Override
+       public Future<RpcResult<AddLspOutput>> addLsp(final AddLspInput input) {
+               final ExecutionResultAdaptor<AddLspOutput> adaptor = new ExecutionResultAdaptor<AddLspOutput>() {
+                       @Override
+                       protected RpcResult<AddLspOutput> convertResult(final OperationResult result) {
+                               return SuccessfulRpcResult.create(new AddLspOutputBuilder(result).build());
+                       }
+               };
+
+               manager.realAddLsp(input).addListener(adaptor);
+               return adaptor.promise;
+       }
+
+       @Override
+       public Future<RpcResult<RemoveLspOutput>> removeLsp(final RemoveLspInput input) {
+               final ExecutionResultAdaptor<RemoveLspOutput> adaptor = new ExecutionResultAdaptor<RemoveLspOutput>() {
+                       @Override
+                       protected RpcResult<RemoveLspOutput> convertResult(final OperationResult result) {
+                               return SuccessfulRpcResult.create(new RemoveLspOutputBuilder(result).build());
+                       }
+               };
+
+               manager.realRemoveLsp(input).addListener(adaptor);
+               return adaptor.promise;
+       }
+
+       @Override
+       public Future<RpcResult<UpdateLspOutput>> updateLsp(final UpdateLspInput input) {
+               final ExecutionResultAdaptor<UpdateLspOutput> adaptor = new ExecutionResultAdaptor<UpdateLspOutput>() {
+                       @Override
+                       protected RpcResult<UpdateLspOutput> convertResult(final OperationResult result) {
+                               return SuccessfulRpcResult.create(new UpdateLspOutputBuilder(result).build());
+                       }
+               };
+
+               manager.realUpdateLsp(input).addListener(adaptor);
+               return adaptor.promise;
+       }
+}