<module>testtool</module>
<module>topology-api</module>
<module>topology-provider</module>
+ <module>topology-spi</module>
<module>tunnel-api</module>
<module>tunnel-provider</module>
</modules>
<artifactId>pcep-topology-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-topology-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
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;
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, GlobalEventExecutor.INSTANCE, null, dps, topology);
+ final PCEPTopologyProvider exp = new PCEPTopologyProvider(dispatcher, null, dps, topology);
final ChannelFuture s = exp.startServer(address);
try {
s.get();
package org.opendaylight.bgpcep.pcep.topology.provider;
import io.netty.channel.ChannelFuture;
-import io.netty.util.concurrent.EventExecutor;
import java.net.InetSocketAddress;
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.manager = new ServerSessionManager(executor, dataService, topology);
- this.element = new TopologyRPCs(executor, manager);
- this.topology = new TopologyProgramming(executor, scheduler, manager);
+ this.manager = new ServerSessionManager(dataService, topology);
+ this.element = new TopologyRPCs(manager);
+ this.topology = new TopologyProgramming(scheduler, manager);
}
public ChannelFuture startServer(final InetSocketAddress address) {
*/
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.net.InetAddress;
import java.util.HashMap;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
/**
*
}
private final class SessionListener implements PCEPSessionListener {
- private final Map<SrpIdNumber, Promise<OperationResult>> waitingRequests = new HashMap<>();
- private final Map<SrpIdNumber, Promise<OperationResult>> sendingRequests = new HashMap<>();
+ private final Map<SrpIdNumber, SettableFuture<OperationResult>> waitingRequests = new HashMap<>();
+ private final Map<SrpIdNumber, SettableFuture<OperationResult>> sendingRequests = new HashMap<>();
private final Map<PlspId, SymbolicPathName> lsps = new HashMap<>();
private PathComputationClientBuilder pccBuilder;
private InstanceIdentifier<Node1> topologyAugment;
}
// Clear all requests which have not been sent to the peer: they result in cancellation
- for (final Entry<SrpIdNumber, Promise<OperationResult>> e : this.sendingRequests.entrySet()) {
+ for (final Entry<SrpIdNumber, SettableFuture<OperationResult>> e : this.sendingRequests.entrySet()) {
LOG.debug("Request {} was not sent when session went down, cancelling the instruction", e.getKey());
- e.getValue().setSuccess(OPERATION_UNSENT);
+ e.getValue().set(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<OperationResult>> e : this.waitingRequests.entrySet()) {
+ for (final Entry<SrpIdNumber, SettableFuture<OperationResult>> e : this.waitingRequests.entrySet()) {
LOG.info("Request {} was incomplete when session went down, failing the instruction", e.getKey());
- e.getValue().setSuccess(OPERATION_NOACK);
+ e.getValue().set(OPERATION_NOACK);
}
this.waitingRequests.clear();
}
case Active:
case Down:
case Up:
- final Promise<OperationResult> p = this.waitingRequests.remove(id);
+ final SettableFuture<OperationResult> p = this.waitingRequests.remove(id);
if (p != null) {
LOG.debug("Request {} resulted in LSP operational state {}", id, lsp.getOperational());
- p.setSuccess(OPERATION_SUCCESS);
+ p.set(OPERATION_SUCCESS);
} else {
LOG.warn("Request ID {} not found in outstanding DB", id);
}
}
private synchronized void messageSendingComplete(final SrpIdNumber requestId, final io.netty.util.concurrent.Future<Void> future) {
- final Promise<OperationResult> promise = this.sendingRequests.remove(requestId);
+ final SettableFuture<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(OPERATION_UNSENT);
+ promise.set(OPERATION_UNSENT);
}
}
- private synchronized io.netty.util.concurrent.Future<OperationResult> sendMessage(final Message message, final SrpIdNumber requestId) {
+ private synchronized ListenableFuture<OperationResult> sendMessage(final Message message, final SrpIdNumber requestId) {
final io.netty.util.concurrent.Future<Void> f = this.session.sendMessage(message);
- final Promise<OperationResult> ret = ServerSessionManager.this.exec.newPromise();
+ final SettableFuture<OperationResult> ret = SettableFuture.create();
this.sendingRequests.put(requestId, ret);
private final Map<NodeId, SessionListener> nodes = new HashMap<>();
private final InstanceIdentifier<Topology> topology;
private final DataProviderService dataProvider;
- private final EventExecutor exec;
- public ServerSessionManager(final EventExecutor exec, final DataProviderService dataProvider,
- final InstanceIdentifier<Topology> topology) {
+ public ServerSessionManager(final DataProviderService dataProvider, final InstanceIdentifier<Topology> topology) {
this.dataProvider = Preconditions.checkNotNull(dataProvider);
this.topology = Preconditions.checkNotNull(topology);
- this.exec = Preconditions.checkNotNull(exec);
}
@Override
return new SessionListener();
}
- synchronized io.netty.util.concurrent.Future<OperationResult> realAddLsp(final AddLspArgs input) {
+ synchronized ListenableFuture<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 this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Make sure there is no such LSP
new ReportedLspsKey(input.getName())).toInstance();
if (this.dataProvider.readOperationalData(lsp) != null) {
LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Build the request
};
}
- synchronized io.netty.util.concurrent.Future<OperationResult> realRemoveLsp(final RemoveLspArgs input) {
+ synchronized ListenableFuture<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 this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Make sure the LSP exists, we need it for PLSP-ID
final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
if (rep == null) {
LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Build the request and send it
return l.sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId());
}
- synchronized io.netty.util.concurrent.Future<OperationResult> realUpdateLsp(final UpdateLspArgs input) {
+ synchronized ListenableFuture<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 this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Make sure the LSP exists
final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
if (rep == null) {
LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Build the PCUpd request and send it
*/
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.pcep.topology.spi.AbstractTopologyProgrammingExecutor;
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.NetworkTopologyPcepProgrammingService;
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;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
/**
*
*/
final class TopologyProgramming implements NetworkTopologyPcepProgrammingService {
- 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) {
+ TopologyProgramming(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) {
+ public ListenableFuture<RpcResult<SubmitAddLspOutput>> submitAddLsp(final SubmitAddLspInput input) {
Preconditions.checkArgument(input.getNode() != null);
Preconditions.checkArgument(input.getName() != null);
- final InstructionExecutor e = new AbstractInstructionExecutor() {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
@Override
- public io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+ public ListenableFuture<OperationResult> executeImpl() {
return manager.realAddLsp(input);
}
};
}
final RpcResult<SubmitAddLspOutput> res = SuccessfulRpcResult.create(b.build());
- return exec.newSucceededFuture(res);
+ return Futures.immediateFuture(res);
}
@Override
- public Future<RpcResult<SubmitRemoveLspOutput>> submitRemoveLsp(final SubmitRemoveLspInput input) {
+ public ListenableFuture<RpcResult<SubmitRemoveLspOutput>> submitRemoveLsp(final SubmitRemoveLspInput input) {
Preconditions.checkArgument(input.getNode() != null);
Preconditions.checkArgument(input.getName() != null);
- final InstructionExecutor e = new AbstractInstructionExecutor() {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
@Override
- protected io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+ protected ListenableFuture<OperationResult> executeImpl() {
return manager.realRemoveLsp(input);
}
};
}
final RpcResult<SubmitRemoveLspOutput> res = SuccessfulRpcResult.create(b.build());
- return exec.newSucceededFuture(res);
+ return Futures.immediateFuture(res);
}
@Override
- public Future<RpcResult<SubmitUpdateLspOutput>> submitUpdateLsp(final SubmitUpdateLspInput input) {
+ public ListenableFuture<RpcResult<SubmitUpdateLspOutput>> submitUpdateLsp(final SubmitUpdateLspInput input) {
Preconditions.checkArgument(input.getNode() != null);
Preconditions.checkArgument(input.getName() != null);
- final InstructionExecutor e = new AbstractInstructionExecutor() {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
@Override
- protected io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+ protected ListenableFuture<OperationResult> executeImpl() {
return manager.realUpdateLsp(input);
}
};
}
final RpcResult<SubmitUpdateLspOutput> res = SuccessfulRpcResult.create(b.build());
- return exec.newSucceededFuture(res);
+ return Futures.immediateFuture(res);
}
}
*/
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.UpdateLspOutputBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import com.google.common.base.Function;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
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) {
+ TopologyRPCs(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>() {
+ return Futures.transform(manager.realAddLsp(input), new Function<OperationResult, RpcResult<AddLspOutput>>() {
@Override
- protected RpcResult<AddLspOutput> convertResult(final OperationResult result) {
- return SuccessfulRpcResult.create(new AddLspOutputBuilder(result).build());
+ public RpcResult<AddLspOutput> apply(final OperationResult input) {
+ return SuccessfulRpcResult.create(new AddLspOutputBuilder(input).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>() {
+ return Futures.transform(manager.realRemoveLsp(input), new Function<OperationResult, RpcResult<RemoveLspOutput>>() {
@Override
- protected RpcResult<RemoveLspOutput> convertResult(final OperationResult result) {
- return SuccessfulRpcResult.create(new RemoveLspOutputBuilder(result).build());
+ public RpcResult<RemoveLspOutput> apply(final OperationResult input) {
+ return SuccessfulRpcResult.create(new RemoveLspOutputBuilder(input).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>() {
+ return Futures.transform(manager.realUpdateLsp(input), new Function<OperationResult, RpcResult<UpdateLspOutput>>() {
@Override
- protected RpcResult<UpdateLspOutput> convertResult(final OperationResult result) {
- return SuccessfulRpcResult.create(new UpdateLspOutputBuilder(result).build());
+ public RpcResult<UpdateLspOutput> apply(final OperationResult input) {
+ return SuccessfulRpcResult.create(new UpdateLspOutputBuilder(input).build());
}
- };
-
- manager.realUpdateLsp(input).addListener(adaptor);
- return adaptor.promise;
+ });
}
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>pcep-topology-spi</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>pcep-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pcep-topology-spi</artifactId>
+ <description>PCEP Topology SPI</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>programming-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>programming-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- FIXME: integrate with config to get rid of this -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.bgpcep.pcep.topology.spi
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>PCEP-TOPOLOGY-SPI Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * 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.spi;
+
+import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
+import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
+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.topology.pcep.rev131024.FailureType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public abstract class AbstractTopologyProgrammingExecutor implements InstructionExecutor {
+
+ protected abstract ListenableFuture<OperationResult> executeImpl();
+
+ @Override
+ public final ListenableFuture<ExecutionResult<Details>> execute() {
+ return Futures.transform(executeImpl(), new Function<OperationResult, ExecutionResult<Details>>() {
+
+ @Override
+ public ExecutionResult<Details> apply(final OperationResult input) {
+ final FailureType fail = input.getFailure();
+ if (fail == null) {
+ return new ExecutionResult<Details>(InstructionStatus.Successful, null);
+ }
+
+ switch (fail) {
+ case Failed:
+ case NoAck:
+ return new ExecutionResult<Details>(InstructionStatus.Failed, null);
+ case Unsent:
+ return new ExecutionResult<Details>(InstructionStatus.Cancelled, null);
+ }
+
+ throw new IllegalStateException("Unhandled operation state " + fail);
+ }
+ });
+ }
+}
namespace "urn:opendaylight:params:xml:ns:yang:topology:tunnel:pcep:programming";
prefix "ttpp";
- import network-topology { prefix nt; revision-date 2013-10-21; }
import pcep-types { prefix pcep; revision-date 2013-10-05; }
- import programming { prefix pgm; revision-date 2013-09-30; }
- import topology-tunnel { prefix tt; revision-date 2013-08-19; }
import topology-tunnel-programming { prefix ttp; revision-date 2013-09-30; }
+ import topology-tunnel-p2p { prefix p2p; revision-date 2013-08-19; }
organization "Cisco Systems, Inc.";
contact "Robert Varga <rovarga@cisco.com>";
reference "";
}
- rpc pcep-create-tunnel {
+ rpc pcep-create-p2p-tunnel {
input {
- uses ttp:create-tunnel-input;
+ uses ttp:create-p2p-tunnel-input;
- leaf symbolic-path-name {
- type pcep:symbolic-path-name;
- mandatory true;
- }
-
- container endpoints {
- uses pcep:endpoints;
- }
-
- leaf signaling-type {
- // FIXME: dedicated type in PCEP
- type uint8;
- default 0;
- }
-
- leaf administrative {
- type boolean;
- default true;
- }
-
- // FIXME: ERO
- // FIXME: attribute-list
+ uses p2p:tunnel-p2p-path-cfg-attributes;
}
output {
- uses ttp:create-tunnel-output;
+ uses ttp:create-p2p-tunnel-output;
}
}
rpc pcep-update-tunnel {
input {
- container update-tunnel {
- leaf topology-id {
- type nt:topology-id;
- mandatory true;
- }
- leaf link-id {
- type nt:link-id;
- mandatory true;
- }
+ uses ttp:base-tunnel-input;
- // FIXME: all that PCUpd jazz
- }
+ uses p2p:tunnel-p2p-path-cfg-attributes;
}
output {
- uses pgm:submit-instruction-output;
+ uses ttp:base-tunnel-output;
}
}
}
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>pcep-topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-topology-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
package org.opendaylight.bgpcep.pcep.tunnel.provider;
+import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// FIXME: migrate to config subsystem
final TunnelTopologyExporter tte = new TunnelTopologyExporter(dps, null);
tte.addTargetTopology(null);
+
+ final InstructionScheduler scheduler = null;
+ final TunnelProgramming tp = new TunnelProgramming(scheduler, session.getRpcService(NetworkTopologyPcepService.class));
}
}
+++ /dev/null
-/*
- * 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.tunnel.provider;
-
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcep;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-public final class PCEPTunnelInstructionExecutor {
- private static final Logger LOG = LoggerFactory.getLogger(PCEPTunnelInstructionExecutor.class);
- private final InstanceIdentifier<Topology> underlay;
- private final InstanceIdentifier<Topology> target;
- private final DataProviderService dps;
-
- private PCEPTunnelInstructionExecutor(final DataProviderService dps, final InstanceIdentifier<Topology> underlay,
- final InstanceIdentifier<Topology> target, final TopologyId topologyId) {
- this.dps = Preconditions.checkNotNull(dps);
- this.underlay = Preconditions.checkNotNull(underlay);
- this.target = Preconditions.checkNotNull(target);
- }
-
- public static PCEPTunnelInstructionExecutor create(final DataProviderService dps, final InstanceIdentifier<Topology> underlay,
- final TopologyId targetId) {
- Preconditions.checkNotNull(dps);
- Preconditions.checkNotNull(targetId);
-
- // Topology pointer
- final InstanceIdentifier<Topology> target = InstanceIdentifier.builder().node(NetworkTopology.class).
- node(Topology.class, new TopologyKey(targetId)).toInstance();
-
- // Now check if there is a container identifying the topology as PCEP-aware
- final InstanceIdentifier<TopologyPcep> i = InstanceIdentifier.builder(target).node(TopologyTypes.class).node(TopologyPcep.class).toInstance();
- final DataObject ttt = dps.readOperationalData(i);
- Preconditions.checkArgument(ttt != null, "Specified topology does not list topology-pcep as its type");
-
- return new PCEPTunnelInstructionExecutor(dps, underlay, target, targetId);
- }
-}
--- /dev/null
+/*
+ * 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.tunnel.provider;
+
+
+import org.opendaylight.bgpcep.pcep.topology.spi.AbstractTopologyProgrammingExecutor;
+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.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.AddLspInputBuilder;
+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.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.RemoveLspInputBuilder;
+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.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.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepDestroyTunnelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepDestroyTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepDestroyTunnelOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepUpdateTunnelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepUpdateTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepUpdateTunnelOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.TopologyTunnelPcepProgrammingService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+final class TunnelProgramming implements TopologyTunnelPcepProgrammingService {
+ private final NetworkTopologyPcepService pcepTopology;
+ private final InstructionScheduler scheduler;
+
+ TunnelProgramming(final InstructionScheduler scheduler, final NetworkTopologyPcepService pcepTopology) {
+ this.scheduler = Preconditions.checkNotNull(scheduler);
+ this.pcepTopology = Preconditions.checkNotNull(pcepTopology);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PcepCreateP2pTunnelOutput>> pcepCreateP2pTunnel(final PcepCreateP2pTunnelInput input) {
+ Preconditions.checkNotNull(input.getLinkId());
+ Preconditions.checkNotNull(input.getSourceTp());
+ Preconditions.checkNotNull(input.getDestinationTp());
+
+ final AddLspInputBuilder ab = new AddLspInputBuilder();
+ ab.fieldsFrom(input);
+
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
+ @Override
+ protected ListenableFuture<OperationResult> executeImpl() {
+ final ListenableFuture<RpcResult<AddLspOutput>> s =
+ (ListenableFuture<RpcResult<AddLspOutput>>) pcepTopology.addLsp(ab.build());
+
+ return Futures.transform(s, new Function<RpcResult<AddLspOutput>, OperationResult>() {
+ @Override
+ public OperationResult apply(final RpcResult<AddLspOutput> input) {
+ return input.getResult();
+ }
+ });
+ }
+ };
+
+ final Failure f = this.scheduler.submitInstruction(input, e);
+ final PcepCreateP2pTunnelOutputBuilder b = new PcepCreateP2pTunnelOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<PcepCreateP2pTunnelOutput> res = SuccessfulRpcResult.create(b.build());
+ return Futures.immediateFuture(res);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PcepDestroyTunnelOutput>> pcepDestroyTunnel(final PcepDestroyTunnelInput input) {
+ Preconditions.checkNotNull(input.getLinkId());
+
+ final RemoveLspInputBuilder ab = new RemoveLspInputBuilder();
+ ab.fieldsFrom(input);
+
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
+ @Override
+ protected ListenableFuture<OperationResult> executeImpl() {
+ final ListenableFuture<RpcResult<RemoveLspOutput>> s =
+ (ListenableFuture<RpcResult<RemoveLspOutput>>) pcepTopology.removeLsp(ab.build());
+
+ return Futures.transform(s, new Function<RpcResult<RemoveLspOutput>, OperationResult>() {
+ @Override
+ public OperationResult apply(final RpcResult<RemoveLspOutput> input) {
+ return input.getResult();
+ }
+ });
+ }
+ };
+
+ final Failure f = this.scheduler.submitInstruction(input, e);
+ final PcepDestroyTunnelOutputBuilder b = new PcepDestroyTunnelOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<PcepDestroyTunnelOutput> res = SuccessfulRpcResult.create(b.build());
+ return Futures.immediateFuture(res);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PcepUpdateTunnelOutput>> pcepUpdateTunnel(final PcepUpdateTunnelInput input) {
+ Preconditions.checkNotNull(input.getLinkId());
+
+ final UpdateLspInputBuilder ab = new UpdateLspInputBuilder();
+ ab.fieldsFrom(input);
+
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
+ @Override
+ protected ListenableFuture<OperationResult> executeImpl() {
+ final ListenableFuture<RpcResult<UpdateLspOutput>> s =
+ (ListenableFuture<RpcResult<UpdateLspOutput>>) pcepTopology.updateLsp(ab.build());
+
+ return Futures.transform(s, new Function<RpcResult<UpdateLspOutput>, OperationResult>() {
+ @Override
+ public OperationResult apply(final RpcResult<UpdateLspOutput> input) {
+ return input.getResult();
+ }
+ });
+ }
+ };
+
+ final Failure f = this.scheduler.submitInstruction(input, e);
+ final PcepUpdateTunnelOutputBuilder b = new PcepUpdateTunnelOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<PcepUpdateTunnelOutput> res = SuccessfulRpcResult.create(b.build());
+ return Futures.immediateFuture(res);
+ }
+}
package org.opendaylight.bgpcep.programming.impl;
import io.netty.util.Timeout;
-import io.netty.util.concurrent.Future;
import java.util.ArrayList;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
final class Instruction {
private final List<Instruction> dependants = new ArrayList<>();
return status;
}
- Future<ExecutionResult<Details>> execute() {
+ ListenableFuture<ExecutionResult<Details>> execute() {
return executor.execute();
}
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.FutureListener;
import java.math.BigInteger;
import java.util.ArrayDeque;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
final class ProgrammingServiceImpl implements InstructionScheduler, ProgrammingService {
private static final Logger LOG = LoggerFactory.getLogger(ProgrammingServiceImpl.class);
Preconditions.checkState(i.getStatus().equals(InstructionStatus.Scheduled));
transitionInstruction(i, InstructionStatus.Executing, null);
- final Future<ExecutionResult<Details>> f = i.execute();
- f.addListener(new FutureListener<ExecutionResult<?>>() {
+ Futures.addCallback(i.execute(), new FutureCallback<ExecutionResult<Details>>() {
+
+ @Override
+ public void onSuccess(final ExecutionResult<Details> result) {
+ executionSuccessful(i, result);
+ }
+
@Override
- public void operationComplete(final Future<ExecutionResult<?>> future) {
- if (future.isSuccess()) {
- executionSuccessful(i, future.getNow());
- } else {
- executionFailed(i, future.cause());
- }
+ public void onFailure(final Throwable t) {
+ executionFailed(i, t);
}
});
}
*/
package org.opendaylight.bgpcep.programming.spi;
-import io.netty.util.concurrent.Future;
-
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
+import com.google.common.util.concurrent.ListenableFuture;
+
public interface InstructionExecutor {
- Future<ExecutionResult<Details>> execute();
+ ListenableFuture<ExecutionResult<Details>> execute();
}
reference "";
}
- grouping create-tunnel-input {
+ grouping base-tunnel-input {
uses tp:topology-instruction-input;
leaf link-id {
}
}
- grouping create-tunnel-output {
+ grouping base-tunnel-output {
uses tp:topology-instruction-output;
}
+ grouping create-tunnel-input {
+ uses base-tunnel-input;
+ }
+
+ grouping create-tunnel-output {
+ uses base-tunnel-output;
+ }
+
grouping destroy-tunnel-input {
- uses tp:topology-instruction-input;
+ uses base-tunnel-input;
+ }
- leaf link-id {
- type nt:link-id;
+ grouping destroy-tunnel-output {
+ uses base-tunnel-output;
+ }
+
+ grouping p2p-tunnel-input {
+ uses base-tunnel-input;
+
+ leaf source-tp {
+ type nt:tp-ref;
+ mandatory true;
+ }
+ leaf destination-tp {
+ type nt:tp-ref;
mandatory true;
}
}
- grouping destroy-tunnel-output {
- uses tp:topology-instruction-output;
+ grouping p2p-tunnel-output {
+ uses base-tunnel-output;
+ }
+
+ grouping create-p2p-tunnel-input {
+ uses p2p-tunnel-input;
+ }
+
+ grouping create-p2p-tunnel-output {
+ uses p2p-tunnel-output;
}
}
}
}
- grouping tunnel-p2p-path-attributes {
+ grouping tunnel-p2p-path-cfg-attributes {
list explicit-hops {
uses tunnel-p2p-path-hops;
key order;
mandatory true;
}
}
+ }
+ grouping tunnel-p2p-path-oper-attributes {
list reported-hops {
+ config false;
uses tunnel-p2p-path-hops;
key order;
}
augment "/nt:network-topology/nt:topology/tt:paths" {
when "../path-types/p2p-tunnel";
- uses tunnel-p2p-path-attributes;
+ uses tunnel-p2p-path-cfg-attributes;
+ uses tunnel-p2p-path-oper-attributes;
}
}