Add Graph mapping to PCEP topology
[bgpcep.git] / pcep / server / server-provider / src / main / java / org / opendaylight / bgpcep / pcep / server / provider / DefaultPceServerProvider.java
1 /*
2  * Copyright (c) 2020 Orange. 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.server.provider;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.HashMap;
13 import java.util.Map;
14 import javax.annotation.PreDestroy;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.algo.PathComputationProvider;
19 import org.opendaylight.bgpcep.pcep.server.PathComputation;
20 import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
21 import org.opendaylight.graph.ConnectedGraph;
22 import org.opendaylight.graph.ConnectedGraphProvider;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.GraphKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.NetworkTopologyPcepService;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
30 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
31 import org.osgi.service.component.annotations.Activate;
32 import org.osgi.service.component.annotations.Component;
33 import org.osgi.service.component.annotations.Deactivate;
34 import org.osgi.service.component.annotations.Reference;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38
39 @Singleton
40 @Component(immediate = true)
41 public final class DefaultPceServerProvider implements PceServerProvider, AutoCloseable {
42     private static final Logger LOG = LoggerFactory.getLogger(DefaultPceServerProvider.class);
43     private final ConnectedGraphProvider graphProvider;
44     private final PathComputationProvider algoProvider;
45     private final DataBroker dataBroker;
46     private final RpcConsumerRegistry rpcRegistry;
47     private Map<TopologyId, PathManagerProvider> pathManagers = new HashMap<TopologyId, PathManagerProvider>();
48     private Map<TopologyId, PathManagerListener> pathListeners = new HashMap<TopologyId, PathManagerListener>();
49     private Map<TopologyId, PcepTopologyListener> pcepListeners = new HashMap<TopologyId, PcepTopologyListener>();
50     private volatile ConnectedGraph tedGraph;
51     private volatile GraphKey graphKey;
52
53     @Inject
54     @Activate
55     public DefaultPceServerProvider(@Reference final ConnectedGraphProvider graphProvider,
56             @Reference final PathComputationProvider pathComputationProvider,
57             @Reference final DataBroker dataBroker,
58             @Reference final RpcConsumerRegistry rpcConsumerRegistry) {
59         this.graphProvider = requireNonNull(graphProvider);
60         this.algoProvider = requireNonNull(pathComputationProvider);
61         this.dataBroker = requireNonNull(dataBroker);
62         this.rpcRegistry = requireNonNull(rpcConsumerRegistry);
63     }
64
65     @Override
66     @Deactivate
67     @PreDestroy
68     public void close() {
69         for (PathManagerListener pathListener: pathListeners.values()) {
70             pathListener.close();
71             pathListener = null;
72         }
73         pathListeners.clear();
74         for (PcepTopologyListener pcepListener: pcepListeners.values()) {
75             pcepListener.close();
76             pcepListener = null;
77         }
78         pcepListeners.clear();
79         for (PathManagerProvider pathManager: pathManagers.values()) {
80             pathManager.close();
81             pathManager = null;
82         }
83         pathManagers.clear();
84     }
85
86     private void closeListenerAndManager(TopologyId key) {
87
88         PathManagerListener pathListener = pathListeners.remove(key);
89         if (pathListener != null) {
90             pathListener.close();
91         }
92         PcepTopologyListener pcepListener = pcepListeners.remove(key);
93         if (pcepListener != null) {
94             pcepListener.close();
95         }
96         PathManagerProvider pathManager = pathManagers.remove(key);
97         if (pathManager != null) {
98             pathManager.close();
99         }
100     }
101
102     @Override
103     public @Nullable PathComputation getPathComputation() {
104         /* Check that we have a valid graph */
105         final ConnectedGraph graph = getTedGraph();
106         return graph == null ? null : new PathComputationImpl(tedGraph, algoProvider);
107     }
108
109     public ConnectedGraph getTedGraph() {
110         /* Leave a chance to get a valid Graph in case of late fulfillment */
111         if (tedGraph == null) {
112             setTedGraph();
113         }
114         return tedGraph;
115     }
116
117     /**
118      * Set Traffic Engineering Graph. This method is necessary as the TedGraph could be available
119      * after the PathComputationFactory start e.g. manual insertion of a ted Graph, or late tedGraph fulfillment
120      * from BGP Link State.
121      */
122     private void setTedGraph() {
123         tedGraph = graphProvider.getConnectedGraph(graphKey);
124     }
125
126     @Override
127     public void registerPcepTopology(KeyedInstanceIdentifier<Topology, TopologyKey> topology, GraphKey key) {
128         TopologyId topoKey = requireNonNull(topology).getKey().getTopologyId();
129         this.graphKey = requireNonNull(key);
130
131         LOG.info("Start PCE Server components for Topology {} with TED {}", topoKey.getValue(), graphKey.getName());
132
133         /* First close current Listener & Manager if there are active */
134         closeListenerAndManager(topoKey);
135
136         /* Then create Path Manger */
137         final NetworkTopologyPcepService ntps = rpcRegistry.getRpcService(NetworkTopologyPcepService.class);
138         PathManagerProvider pathManager = new PathManagerProvider(dataBroker, topology, ntps, this);
139
140         /* And Listener */
141         PathManagerListener pathListener = new PathManagerListener(dataBroker, topology, pathManager);
142         PcepTopologyListener pcepListener = new PcepTopologyListener(dataBroker, topology, pathManager);
143
144         /* Finally, register all of them for later deletion */
145         pathManagers.put(topoKey, pathManager);
146         pathListeners.put(topoKey, pathListener);
147         pcepListeners.put(topoKey, pcepListener);
148     }
149
150     @Override
151     public void unRegisterPcepTopology(KeyedInstanceIdentifier<Topology, TopologyKey> topology) {
152         TopologyId topoKey = requireNonNull(topology).getKey().getTopologyId();
153         this.graphKey = null;
154
155         LOG.info("Stop PCE Server for Topology {}", topoKey.getValue());
156         closeListenerAndManager(topoKey);
157     }
158 }