X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=pcep%2Ftopology%2Ftopology-provider%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fbgpcep%2Fpcep%2Ftopology%2Fprovider%2FServerSessionManager.java;h=20440f3a78e94a20502528b97f299b68980d94ec;hb=b85eb1ab9921837175ac1923c1a8a808947e6f03;hp=d1ce610e3b05b21a432ea9fbfa89aacb8daa68e2;hpb=094efd15ff17d6ab122dcd92c563154441b5d83e;p=bgpcep.git diff --git a/pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java b/pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java index d1ce610e3b..20440f3a78 100644 --- a/pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java +++ b/pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java @@ -14,108 +14,154 @@ import com.google.common.util.concurrent.FluentFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.SettableFuture; import java.net.InetAddress; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import org.checkerframework.checker.lock.qual.GuardedBy; import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyConfiguration; -import org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyProviderDependencies; -import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry; +import org.opendaylight.bgpcep.pcep.server.PceServerProvider; import org.opendaylight.mdsal.binding.api.WriteTransaction; import org.opendaylight.mdsal.common.api.CommitInfo; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; -import org.opendaylight.protocol.pcep.PCEPDispatcherDependencies; -import org.opendaylight.protocol.pcep.PCEPSession; import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.GraphKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.PcepSessionState; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspArgs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.EnsureLspOperationalInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.OperationResult; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.RemoveLspArgs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.TearDownSessionInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.TearDownSessionInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.TopologyTypes1Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.TriggerSyncArgs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.UpdateLspArgs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.topology.pcep.type.TopologyPcepBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; -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.TopologyBuilder; 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.Node; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; -import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.ErrorType; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; // Non-final for testing -class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessionRPCs, TopologySessionStatsRegistry { +class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessionRPCs { private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class); private static final long DEFAULT_HOLD_STATE_NANOS = TimeUnit.MINUTES.toNanos(5); + private final @NonNull KeyedInstanceIdentifier topology; + private final @NonNull PCEPTopologyProviderDependencies dependencies; + @VisibleForTesting final AtomicBoolean isClosed = new AtomicBoolean(false); @GuardedBy("this") private final Map nodes = new HashMap<>(); @GuardedBy("this") private final Map state = new HashMap<>(); - private final InstanceIdentifier topology; - private final short rpcTimeout; - private final PCEPTopologyProviderDependencies dependencies; - private final PCEPDispatcherDependencies pcepDispatcherDependencies; - - ServerSessionManager( - final PCEPTopologyProviderDependencies dependencies, - final PCEPTopologyConfiguration configuration) { + + private volatile short rpcTimeout; + + private final GraphKey graphKey; + + ServerSessionManager(final KeyedInstanceIdentifier instanceIdentifier, + final PCEPTopologyProviderDependencies dependencies, final short rpcTimeout, final GraphKey graphKey) { this.dependencies = requireNonNull(dependencies); - topology = requireNonNull(configuration.getTopology()); - rpcTimeout = configuration.getRpcTimeout(); - pcepDispatcherDependencies = new PCEPDispatcherDependenciesImpl(this, - new PCEPStatefulPeerProposal(dependencies.getDataBroker(), topology, configuration.getSpeakerIds()), - configuration); + topology = requireNonNull(instanceIdentifier); + this.rpcTimeout = rpcTimeout; + this.graphKey = requireNonNull(graphKey); } - /** - * Create Base Topology. - */ - final synchronized void instantiateServiceInstance() { - final TopologyKey key = InstanceIdentifier.keyOf(topology); - final TopologyId topologyId = key.getTopologyId(); - final WriteTransaction tx = dependencies.getDataBroker().newWriteOnlyTransaction(); - tx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, topology, new TopologyBuilder() - .withKey(key) - .setTopologyId(topologyId).setTopologyTypes(new TopologyTypesBuilder() - .addAugmentation(new TopologyTypes1Builder() - .setTopologyPcep(new TopologyPcepBuilder().build()) - .build()) + // Initialize the operational view of the topology. + final ListenableFuture start() { + LOG.info("Creating PCEP Topology {}", topologyId()); + final var tx = dependencies.getDataBroker().newWriteOnlyTransaction(); + tx.put(LogicalDatastoreType.OPERATIONAL, topology, new TopologyBuilder() + .withKey(topology.getKey()) + .setTopologyTypes(new TopologyTypesBuilder() + .addAugmentation(new TopologyTypes1Builder().setTopologyPcep(new TopologyPcepBuilder().build()).build()) .build()) .build()); - try { - tx.commit().get(); - LOG.info("PCEP Topology {} created successfully.", topologyId.getValue()); - ServerSessionManager.this.isClosed.set(false); - } catch (final ExecutionException | InterruptedException throwable) { - LOG.error("Failed to create PCEP Topology {}.", topologyId.getValue(), throwable); - ServerSessionManager.this.isClosed.set(true); + + final var future = SettableFuture.create(); + final var txFuture = tx.commit(); + txFuture.addCallback(new FutureCallback() { + @Override + public void onSuccess(final CommitInfo result) { + LOG.info("PCEP Topology {} created successfully.", topologyId()); + isClosed.set(false); + future.set(Boolean.TRUE); + } + + @Override + public void onFailure(final Throwable failure) { + LOG.error("Failed to create PCEP Topology {}.", topologyId(), failure); + isClosed.set(true); + future.set(Boolean.FALSE); + } + }, MoreExecutors.directExecutor()); + + // Register this new topology to PCE Server + final PceServerProvider server = dependencies.getPceServerProvider(); + if (server != null) { + server.registerPcepTopology(topology, graphKey); } + return future; } - final synchronized void releaseNodeState(final TopologyNodeState nodeState, final PCEPSession session, + final synchronized FluentFuture stop() { + if (isClosed.getAndSet(true)) { + LOG.error("Session Manager has already been closed."); + return CommitInfo.emptyFluentFuture(); + } + for (final TopologySessionListener node : nodes.values()) { + node.close(); + } + nodes.clear(); + for (final TopologyNodeState topologyNodeState : state.values()) { + topologyNodeState.close(); + } + state.clear(); + + // Un-Register Pcep Topology into PCE Server + final PceServerProvider server = dependencies.getPceServerProvider(); + if (server != null) { + server.unRegisterPcepTopology(topology); + } + + final WriteTransaction t = dependencies.getDataBroker().newWriteOnlyTransaction(); + t.delete(LogicalDatastoreType.OPERATIONAL, topology); + final FluentFuture future = t.commit(); + future.addCallback(new FutureCallback() { + @Override + public void onSuccess(final CommitInfo result) { + LOG.debug("Topology {} removed", topology); + } + + @Override + public void onFailure(final Throwable throwable) { + LOG.warn("Failed to remove Topology {}", topology, throwable); + } + }, MoreExecutors.directExecutor()); + return future; + } + + final synchronized void releaseNodeState(final TopologyNodeState nodeState, final InetAddress peerAddress, final boolean persistNode) { if (isClosed.get()) { LOG.error("Session Manager has already been closed."); return; } - final NodeId nodeId = createNodeId(session.getRemoteAddress()); + final NodeId nodeId = createNodeId(peerAddress); nodes.remove(nodeId); state.remove(nodeId); if (nodeState != null) { @@ -210,60 +256,33 @@ class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessio } return RpcResultBuilder.failed() - .withError(RpcError.ErrorType.RPC, "Failed to find session " + nodeId) + .withError(ErrorType.RPC, "Failed to find session " + nodeId) .buildFuture(); } - final synchronized FluentFuture closeServiceInstance() { - if (isClosed.getAndSet(true)) { - LOG.error("Session Manager has already been closed."); - return CommitInfo.emptyFluentFuture(); - } - for (final TopologySessionListener node : nodes.values()) { - node.close(); - } - nodes.clear(); - for (final TopologyNodeState topologyNodeState : state.values()) { - topologyNodeState.close(); - } - state.clear(); - - final WriteTransaction t = dependencies.getDataBroker().newWriteOnlyTransaction(); - t.delete(LogicalDatastoreType.OPERATIONAL, topology); - final FluentFuture future = t.commit(); - future.addCallback(new FutureCallback() { - @Override - public void onSuccess(final CommitInfo result) { - LOG.debug("Topology {} removed", topology); - } + final short getRpcTimeout() { + return rpcTimeout; + } - @Override - public void onFailure(final Throwable throwable) { - LOG.warn("Failed to remove Topology {}", topology, throwable); - } - }, MoreExecutors.directExecutor()); - return future; + final void setRpcTimeout(final short rpcTimeout) { + this.rpcTimeout = rpcTimeout; } - final short getRpcTimeout() { - return rpcTimeout; + final void tearDownSessions(final List outdatedNodes) { + for (var address : outdatedNodes) { + tearDownSession(new TearDownSessionInputBuilder().setNode(createNodeId(address)).build()); + } } - @Override - public final synchronized void bind(final KeyedInstanceIdentifier nodeId, + final synchronized void bind(final KeyedInstanceIdentifier nodeId, final PcepSessionState sessionState) { dependencies.getStateRegistry().bind(nodeId, sessionState); } - @Override - public final synchronized void unbind(final KeyedInstanceIdentifier nodeId) { + final synchronized void unbind(final KeyedInstanceIdentifier nodeId) { dependencies.getStateRegistry().unbind(nodeId); } - final PCEPDispatcherDependencies getPCEPDispatcherDependencies() { - return pcepDispatcherDependencies; - } - final PCEPTopologyProviderDependencies getPCEPTopologyProviderDependencies() { return dependencies; } @@ -271,4 +290,8 @@ class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessio static @NonNull NodeId createNodeId(final InetAddress addr) { return new NodeId("pcc://" + addr.getHostAddress()); } + + private @NonNull String topologyId() { + return TopologyUtils.friendlyId(topology); + } } \ No newline at end of file