Bump upstreams
[bgpcep.git] / pcep / tunnel / tunnel-provider / src / main / java / org / opendaylight / bgpcep / pcep / tunnel / provider / TunnelProviderDeployer.java
1 /*
2  * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.bgpcep.pcep.tunnel.provider;
9
10 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
11
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.concurrent.TimeUnit;
16 import org.apache.commons.lang3.StringUtils;
17 import org.checkerframework.checker.lock.qual.GuardedBy;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
20 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
21 import org.opendaylight.mdsal.binding.api.DataTreeModification;
22 import org.opendaylight.mdsal.binding.api.RpcProviderService;
23 import org.opendaylight.mdsal.binding.api.RpcService;
24 import org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.config.rev181109.PcepTunnelTopologyConfig;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.TopologyTypes1;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
32 import org.opendaylight.yangtools.concepts.Registration;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.osgi.framework.BundleContext;
35 import org.osgi.service.component.annotations.Activate;
36 import org.osgi.service.component.annotations.Component;
37 import org.osgi.service.component.annotations.Deactivate;
38 import org.osgi.service.component.annotations.Reference;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 @Component(service = { })
43 public final class TunnelProviderDeployer implements DataTreeChangeListener<Topology>, AutoCloseable {
44     private static final Logger LOG = LoggerFactory.getLogger(TunnelProviderDeployer.class);
45     private static final long TIMEOUT_NS = TimeUnit.SECONDS.toNanos(5);
46
47     private final TunnelProviderDependencies dependencies;
48     @GuardedBy("this")
49     private final Map<TopologyId, PCEPTunnelClusterSingletonService> pcepTunnelServices = new HashMap<>();
50     private final Registration reg;
51
52     @Activate
53     public TunnelProviderDeployer(@Reference final DataBroker dataBroker,
54             @Reference final RpcProviderService rpcProviderRegistry,
55             @Reference final RpcService rpcService,
56             @Reference final ClusterSingletonServiceProvider cssp,
57             // FIXME: do not reference BundleContext in an alternative constructor
58             final BundleContext bundleContext) {
59         dependencies = new TunnelProviderDependencies(dataBroker, cssp, rpcProviderRegistry, rpcService,
60                 bundleContext);
61         reg = dataBroker.registerTreeChangeListener(DataTreeIdentifier.of(CONFIGURATION,
62                 InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).build()), this);
63         LOG.info("Tunnel Provider Deployer created");
64     }
65
66     @Deactivate
67     @Override
68     public synchronized void close() {
69         reg.close();
70         pcepTunnelServices.values().iterator().forEachRemaining(PCEPTunnelClusterSingletonService::close);
71         pcepTunnelServices.clear();
72         LOG.info("Tunnel Provider Deployer closed");
73     }
74
75     @SuppressWarnings("checkstyle:IllegalCatch")
76     private static void closeTopology(final PCEPTunnelClusterSingletonService topology, final TopologyId topologyId) {
77         if (topology != null) {
78             try {
79                 topology.closeServiceInstance().get(TIMEOUT_NS, TimeUnit.NANOSECONDS);
80             } catch (final Exception e) {
81                 LOG.error("Topology {} instance failed to close service instance", topologyId, e);
82             }
83             topology.close();
84         }
85     }
86
87     @Override
88     public synchronized void onDataTreeChanged(final List<DataTreeModification<Topology>> changes) {
89         changes.stream().map(DataTreeModification::getRootNode).forEach(topo -> {
90             switch (topo.modificationType()) {
91                 case SUBTREE_MODIFIED:
92                     updateTunnelTopologyProvider(topo.dataAfter());
93                     break;
94                 case WRITE:
95                     createTunnelTopologyProvider(topo.dataAfter());
96                     break;
97                 case DELETE:
98                     removeTunnelTopologyProvider(topo.dataBefore());
99                     break;
100                 default:
101             }
102         });
103     }
104
105     private static boolean filterPcepTopologies(final TopologyTypes topologyTypes) {
106         if (topologyTypes == null) {
107             return false;
108         }
109         final TopologyTypes1 aug = topologyTypes.augmentation(TopologyTypes1.class);
110         return aug != null && aug.getTopologyTunnelPcep() != null;
111     }
112
113     private synchronized void createTunnelTopologyProvider(final Topology topology) {
114         if (!filterPcepTopologies(topology.getTopologyTypes())) {
115             return;
116         }
117         final TopologyId topologyId = topology.getTopologyId();
118         if (pcepTunnelServices.containsKey(topology.getTopologyId())) {
119             LOG.warn("Tunnel Topology {} already exist. New instance won't be created", topologyId);
120             return;
121         }
122         LOG.debug("Create Tunnel Topology {}", topologyId);
123
124         final PcepTunnelTopologyConfig config = topology.augmentation(PcepTunnelTopologyConfig.class);
125         final String pcepTopoID = StringUtils
126                 .substringBetween(config.getPcepTopologyReference().getValue(), "=\"", "\"");
127         final InstanceIdentifier<Topology> pcepTopoRef = InstanceIdentifier.builder(NetworkTopology.class)
128                 .child(Topology.class, new TopologyKey(new TopologyId(pcepTopoID))).build();
129
130
131         final PCEPTunnelClusterSingletonService tunnelTopoCss =
132                 new PCEPTunnelClusterSingletonService(dependencies, pcepTopoRef, topologyId);
133         pcepTunnelServices.put(topology.getTopologyId(), tunnelTopoCss);
134     }
135
136     private synchronized void updateTunnelTopologyProvider(final Topology topology) {
137         if (!filterPcepTopologies(topology.getTopologyTypes())) {
138             return;
139         }
140         final TopologyId topologyId = topology.getTopologyId();
141         final PCEPTunnelClusterSingletonService previous = pcepTunnelServices.remove(topology.getTopologyId());
142         closeTopology(previous, topologyId);
143         createTunnelTopologyProvider(topology);
144     }
145
146     private synchronized void removeTunnelTopologyProvider(final Topology topo) {
147         if (!filterPcepTopologies(topo.getTopologyTypes())) {
148             return;
149         }
150         final TopologyId topologyId = topo.getTopologyId();
151         final PCEPTunnelClusterSingletonService topology = pcepTunnelServices.remove(topologyId);
152         closeTopology(topology, topologyId);
153     }
154 }