2 * Copyright (c) 2017 AT&T Intellectual Property. 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.tunnel.provider;
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.List;
16 import java.util.concurrent.TimeUnit;
17 import java.util.stream.Collectors;
18 import javax.annotation.Nonnull;
19 import javax.annotation.concurrent.GuardedBy;
20 import org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyDeployerImpl;
21 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
25 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
26 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
27 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.config.rev171127.PcepTunnelTopologyConfig;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.TopologyTypes1;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.osgi.framework.BundleContext;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 public final class TunnelProviderDeployer implements ClusteredDataTreeChangeListener<Topology>, AutoCloseable {
43 private static final Logger LOG = LoggerFactory.getLogger(PCEPTopologyDeployerImpl.class);
45 private static final long TIMEOUT_NS = TimeUnit.SECONDS.toNanos(5);
46 private final TunnelProviderDependencies dependencies;
47 private final InstanceIdentifier<Topology> networTopology;
49 private final Map<TopologyId, PCEPTunnelClusterSingletonService> pcepTunnelServices = new HashMap<>();
51 private ListenerRegistration<TunnelProviderDeployer> listenerRegistration;
53 public TunnelProviderDeployer(
54 final DataBroker dataBroker,
55 final RpcProviderRegistry rpcProviderRegistry,
56 final BundleContext bundleContext,
57 final ClusterSingletonServiceProvider cssp
59 this.dependencies = new TunnelProviderDependencies(dataBroker, cssp, rpcProviderRegistry, bundleContext);
60 this.networTopology = InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).build();
63 @SuppressWarnings("checkstyle:IllegalCatch")
64 private static void closeTopology(final PCEPTunnelClusterSingletonService topology, final TopologyId topologyId) {
65 if (topology != null) {
67 topology.closeServiceInstance().get(TIMEOUT_NS, TimeUnit.NANOSECONDS);
68 } catch (final Exception e) {
69 LOG.error("Topology {} instance failed to close service instance", topologyId, e);
75 public synchronized void init() {
76 this.listenerRegistration = this.dependencies.getDataBroker().registerDataTreeChangeListener(
77 new DataTreeIdentifier<>(CONFIGURATION, this.networTopology), this);
81 public synchronized void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Topology>> changes) {
82 final List<DataObjectModification<Topology>> topoChanges = changes.stream()
83 .map(DataTreeModification::getRootNode)
84 .collect(Collectors.toList());
86 topoChanges.stream().iterator().forEachRemaining(this::handleTopologyChange);
89 private synchronized void handleTopologyChange(final DataObjectModification<Topology> topo) {
90 switch (topo.getModificationType()) {
91 case SUBTREE_MODIFIED:
92 updateTunnelTopologyProvider(topo.getDataAfter());
95 createTunnelTopologyProvider(topo.getDataAfter());
98 removeTunnelTopologyProvider(topo.getDataBefore());
104 private boolean filterPcepTopologies(final TopologyTypes topologyTypes) {
105 if (topologyTypes == null) {
108 final TopologyTypes1 aug = topologyTypes.getAugmentation(TopologyTypes1.class);
109 return aug != null && aug.getTopologyTunnelPcep() != null;
112 private synchronized void createTunnelTopologyProvider(final Topology topology) {
113 if (!filterPcepTopologies(topology.getTopologyTypes())) {
116 final TopologyId topologyId = topology.getTopologyId();
117 if (this.pcepTunnelServices.containsKey(topology.getTopologyId())) {
118 LOG.warn("Tunnel Topology {} already exist. New instance won't be created", topologyId);
122 final PcepTunnelTopologyConfig config = topology.getAugmentation(PcepTunnelTopologyConfig.class);
123 final String pcepTopoID = config.getPcepTopologyReference().getValue();
125 final InstanceIdentifier<Topology> pcepTopoRef = InstanceIdentifier.builder(NetworkTopology.class)
126 .child(Topology.class, new TopologyKey(new TopologyId(pcepTopoID))).build();
129 final PCEPTunnelClusterSingletonService tunnelTopoCss =
130 new PCEPTunnelClusterSingletonService(this.dependencies, pcepTopoRef, topologyId);
131 this.pcepTunnelServices.put(topology.getTopologyId(), tunnelTopoCss);
134 private synchronized void updateTunnelTopologyProvider(final Topology topology) {
135 if (!filterPcepTopologies(topology.getTopologyTypes())) {
138 final TopologyId topologyId = topology.getTopologyId();
139 final PCEPTunnelClusterSingletonService previous = this.pcepTunnelServices.remove(topology.getTopologyId());
140 closeTopology(previous, topologyId);
141 createTunnelTopologyProvider(topology);
144 private synchronized void removeTunnelTopologyProvider(final Topology topo) {
145 if (!filterPcepTopologies(topo.getTopologyTypes())) {
148 final TopologyId topologyId = topo.getTopologyId();
149 final PCEPTunnelClusterSingletonService topology = this.pcepTunnelServices.remove(topologyId);
150 closeTopology(topology, topologyId);
154 public synchronized void close() {
155 if (this.listenerRegistration != null) {
156 this.listenerRegistration.close();
157 this.listenerRegistration = null;
159 this.pcepTunnelServices.values().iterator().forEachRemaining(PCEPTunnelClusterSingletonService::close);
160 this.pcepTunnelServices.clear();