2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.bgpcep.pcep.topology.provider.config;
10 import static java.util.Objects.requireNonNull;
12 import java.util.Collection;
13 import java.util.HashMap;
15 import java.util.concurrent.TimeUnit;
16 import org.checkerframework.checker.lock.qual.GuardedBy;
17 import org.checkerframework.checker.lock.qual.Holding;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
20 import org.opendaylight.bgpcep.pcep.topology.provider.TopologySessionListenerFactory;
21 import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry;
22 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
23 import org.opendaylight.bgpcep.programming.spi.InstructionSchedulerFactory;
24 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
27 import org.opendaylight.mdsal.binding.api.DataTreeModification;
28 import org.opendaylight.mdsal.binding.api.RpcProviderService;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
31 import org.opendaylight.protocol.pcep.PCEPDispatcher;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.config.rev200120.pcep.config.SessionConfig;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.config.rev181109.PcepTopologyTypeConfig;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.TopologyTypes1;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
39 import org.opendaylight.yangtools.concepts.ListenerRegistration;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.osgi.framework.BundleContext;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 public class PCEPTopologyDeployerImpl implements ClusteredDataTreeChangeListener<Topology>, AutoCloseable {
46 private static final Logger LOG = LoggerFactory.getLogger(PCEPTopologyDeployerImpl.class);
47 private static final long TIMEOUT_NS = TimeUnit.SECONDS.toNanos(5);
49 private final InstructionSchedulerFactory instructionSchedulerFactory;
50 private final TopologySessionListenerFactory sessionListenerFactory;
51 private final ClusterSingletonServiceProvider singletonService;
52 private final PCEPDispatcher pcepDispatcher;
53 private final DataBroker dataBroker;
54 private final RpcProviderService rpcProviderRegistry;
55 private final TopologySessionStatsRegistry stateRegistry;
56 private final PceServerProvider pceServerProvider;
57 private final BundleContext bundleContext;
60 private final Map<TopologyId, PCEPTopologyProviderBean> pcepTopologyServices = new HashMap<>();
62 private ListenerRegistration<PCEPTopologyDeployerImpl> listenerRegistration;
64 public PCEPTopologyDeployerImpl(final DataBroker dataBroker, final ClusterSingletonServiceProvider singletonService,
65 final RpcProviderService rpcProviderRegistry, final PCEPDispatcher pcepDispatcher,
66 final TopologySessionListenerFactory sessionListenerFactory,
67 final InstructionSchedulerFactory instructionSchedulerFactory,
68 final TopologySessionStatsRegistry stateRegistry, final PceServerProvider pceServerProvider,
69 // FIXME: we should not be needing this OSGi dependency
70 final BundleContext bundleContext) {
71 this.dataBroker = requireNonNull(dataBroker);
72 this.singletonService = requireNonNull(singletonService);
73 this.rpcProviderRegistry = requireNonNull(rpcProviderRegistry);
74 this.pcepDispatcher = requireNonNull(pcepDispatcher);
75 this.sessionListenerFactory = requireNonNull(sessionListenerFactory);
76 this.instructionSchedulerFactory = requireNonNull(instructionSchedulerFactory);
77 this.stateRegistry = requireNonNull(stateRegistry);
78 this.pceServerProvider = requireNonNull(pceServerProvider);
79 this.bundleContext = requireNonNull(bundleContext);
82 public synchronized void init() {
83 LOG.info("PCEP Topology Deployer initialized");
84 listenerRegistration = dataBroker.registerDataTreeChangeListener(
85 DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION,
86 InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).build()), this);
90 public synchronized void onDataTreeChanged(final Collection<DataTreeModification<Topology>> changes) {
91 for (var change : changes) {
92 final var topo = change.getRootNode();
93 switch (topo.getModificationType()) {
94 case SUBTREE_MODIFIED:
96 // FIXME: BGPCEP-983: propagate all modifications
97 updateTopologyProvider(topo.getDataAfter());
100 removeTopologyProvider(topo.getDataBefore());
103 throw new IllegalStateException("Unhandled modification type " + topo.getModificationType());
109 private void updateTopologyProvider(final Topology topology) {
110 if (!filterPcepTopologies(topology.getTopologyTypes())) {
113 final TopologyId topologyId = topology.getTopologyId();
114 LOG.info("Updating Topology {}", topologyId);
115 final PCEPTopologyProviderBean previous = pcepTopologyServices.remove(topologyId);
116 closeTopology(previous, topologyId);
117 createTopologyProvider(topology);
121 private void createTopologyProvider(final Topology topology) {
122 if (!filterPcepTopologies(topology.getTopologyTypes())) {
125 final TopologyId topologyId = topology.getTopologyId();
126 if (pcepTopologyServices.containsKey(topologyId)) {
127 LOG.warn("Topology Provider {} already exist. New instance won't be created", topologyId);
130 LOG.info("Creating Topology {}", topologyId);
131 LOG.trace("Topology {}.", topology);
133 final SessionConfig config = topology.augmentation(PcepTopologyTypeConfig.class).getSessionConfig();
134 final InstructionScheduler instructionScheduler = instructionSchedulerFactory
135 .createInstructionScheduler(topologyId.getValue());
137 final PCEPTopologyProviderBean pcepTopologyProviderBean = new PCEPTopologyProviderBean(singletonService,
138 bundleContext, dataBroker, pcepDispatcher, rpcProviderRegistry, sessionListenerFactory, stateRegistry,
140 pcepTopologyServices.put(topologyId, pcepTopologyProviderBean);
142 pcepTopologyProviderBean.start(new PCEPTopologyConfiguration(config, topology), instructionScheduler);
146 private synchronized void removeTopologyProvider(final Topology topology) {
147 if (!filterPcepTopologies(topology.getTopologyTypes())) {
150 final TopologyId topologyId = topology.getTopologyId();
151 closeTopology(pcepTopologyServices.remove(topologyId), topologyId);
155 public synchronized void close() {
156 LOG.info("PCEP Topology Deployer closing");
157 if (listenerRegistration != null) {
158 listenerRegistration.close();
159 listenerRegistration = null;
161 for (Map.Entry<TopologyId, PCEPTopologyProviderBean> entry : pcepTopologyServices.entrySet()) {
162 closeTopology(entry.getValue(), entry.getKey());
164 pcepTopologyServices.clear();
165 LOG.info("PCEP Topology Deployer closed");
168 @SuppressWarnings("checkstyle:IllegalCatch")
169 private static void closeTopology(final PCEPTopologyProviderBean topology, final TopologyId topologyId) {
170 if (topology == null) {
173 LOG.info("Removing Topology {}", topologyId);
175 topology.closeServiceInstance().get(TIMEOUT_NS, TimeUnit.NANOSECONDS);
177 } catch (final Exception e) {
178 LOG.error("Topology {} instance failed to close service instance", topologyId, e);
182 private static boolean filterPcepTopologies(final @Nullable TopologyTypes topologyTypes) {
183 if (topologyTypes == null) {
186 final TopologyTypes1 aug = topologyTypes.augmentation(TopologyTypes1.class);
187 return aug != null && aug.getTopologyPcep() != null;