Do not propagate PCEPSession in onSessionUp
[bgpcep.git] / pcep / topology / topology-stats / src / main / java / org / opendaylight / bgpcep / pcep / topology / stats / rpc / TopologyStatsRpcServiceImpl.java
1 /*
2  * Copyright (c) 2019 Lumina Networks, Inc. and others.  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.topology.stats.rpc;
9
10 import com.google.common.util.concurrent.Futures;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.Collection;
13 import java.util.List;
14 import java.util.concurrent.ConcurrentHashMap;
15 import java.util.concurrent.ConcurrentMap;
16 import java.util.stream.Collectors;
17 import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
18 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
19 import org.opendaylight.mdsal.binding.api.DataBroker;
20 import org.opendaylight.mdsal.binding.api.DataObjectModification;
21 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.PcepEntityIdRpcAugBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.PcepEntityIdStatsAug;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulCapabilitiesRpcAugBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulCapabilitiesStatsAug;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulMessagesRpcAugBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulMessagesStatsAug;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.LocalPref;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.LocalPrefBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.Messages;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.MessagesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.PeerCapabilities;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.PeerCapabilitiesBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.grouping.PcepSessionState;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.grouping.PcepSessionStateBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.GetStatsInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.GetStatsOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.GetStatsOutputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.PcepTopologyStatsRpcService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.stats.rev181109.PcepTopologyNodeStatsAug;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
50 import org.opendaylight.yangtools.concepts.ListenerRegistration;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
53 import org.opendaylight.yangtools.yang.common.RpcResult;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 public final class TopologyStatsRpcServiceImpl
58         implements PcepTopologyStatsRpcService, ClusteredDataTreeChangeListener<PcepSessionState>, AutoCloseable {
59     private static final Logger LOG = LoggerFactory.getLogger(TopologyStatsRpcServiceImpl.class);
60
61     private final ConcurrentMap<InstanceIdentifier<PcepSessionState>, PcepSessionState> sessionStateMap =
62             new ConcurrentHashMap<>();
63     private ListenerRegistration<TopologyStatsRpcServiceImpl> listenerRegistration;
64
65     public TopologyStatsRpcServiceImpl(final DataBroker dataBroker) {
66         LOG.info("Initializing PCEP Topology Stats RPC service.");
67         listenerRegistration = dataBroker.registerDataTreeChangeListener(
68             DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
69                 InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).child(Node.class)
70                     .augmentation(PcepTopologyNodeStatsAug.class).child(PcepSessionState.class).build()),
71             this);
72     }
73
74     @Override
75     public void onDataTreeChanged(final Collection<DataTreeModification<PcepSessionState>> changes) {
76         changes.forEach(change -> {
77             final InstanceIdentifier<PcepSessionState> iid = change.getRootPath().getRootIdentifier();
78             final DataObjectModification<PcepSessionState> mod = change.getRootNode();
79             switch (mod.getModificationType()) {
80                 case SUBTREE_MODIFIED:
81                 case WRITE:
82                     sessionStateMap.put(iid, mod.getDataAfter());
83                     break;
84                 case DELETE:
85                     sessionStateMap.remove(iid);
86                     break;
87                 default:
88             }
89         });
90     }
91
92     @Override
93     public synchronized void close() {
94         if (listenerRegistration != null) {
95             LOG.info("Closing PCEP Topology Stats RPC service.");
96             listenerRegistration.close();
97             listenerRegistration = null;
98         }
99     }
100
101     @Override
102     public ListenableFuture<RpcResult<GetStatsOutput>> getStats(final GetStatsInput input) {
103         final var iTopologies = input.getTopology();
104         final List<TopologyId> iTopologyIds;
105         if (iTopologies != null) {
106             iTopologyIds = iTopologies.values().stream()
107                     .map(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc
108                         .rev190321.get.stats.input.Topology::getTopologyId)
109                     .collect(Collectors.toList());
110         } else {
111             iTopologyIds = getAvailableTopologyIds();
112         }
113
114         return Futures.immediateFuture(SuccessfulRpcResult.create(new GetStatsOutputBuilder()
115             .setTopology(iTopologyIds.stream()
116                 .map(iTopologyId -> {
117                     final Collection<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology
118                         .stats.rpc.rev190321.get.stats.input.topology.Node> iNodes;
119                     if (iTopologies != null) {
120                         final var nodes = iTopologies.values().stream()
121                             .filter(t -> iTopologyId.equals(t.getTopologyId()))
122                             .findFirst()
123                             .get().getNode();
124                         iNodes = nodes != null ? nodes.values() : null;
125                     } else {
126                         iNodes = null;
127                     }
128
129                     final List<NodeId> iNodeIds;
130                     if (iNodes != null) {
131                         iNodeIds = iNodes.stream()
132                             .map(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats
133                                 .rpc.rev190321.get.stats.input.topology.Node::getNodeId)
134                             .collect(Collectors.toList());
135                     } else {
136                         iNodeIds = getAvailableNodeIds(iTopologyId);
137                     }
138
139                     return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc
140                         .rev190321.get.stats.output.TopologyBuilder()
141                         .setTopologyId(iTopologyId)
142                         .setNode(iNodeIds.stream()
143                             .map(iNodeId -> {
144                                 final PcepSessionState state = sessionStateMap.get(
145                                     InstanceIdentifier.builder(NetworkTopology.class)
146                                         .child(Topology.class, new TopologyKey(iTopologyId))
147                                         .child(Node.class, new NodeKey(iNodeId))
148                                         .augmentation(PcepTopologyNodeStatsAug.class)
149                                         .child(PcepSessionState.class)
150                                         .build());
151                                 if (state == null) {
152                                     LOG.debug("Pcep session stats not available for node {} in topology {}",
153                                         iNodeId.getValue(), iTopologyId.getValue());
154                                 }
155                                 return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep
156                                     .topology.stats.rpc.rev190321.get.stats.output.topology.NodeBuilder()
157                                     .setNodeId(iNodeId)
158                                     .setPcepSessionState(transformStatefulAugmentation(state))
159                                     .build();
160                             })
161                             .collect(BindingMap.toOrderedMap()))
162                         .build();
163                 })
164                 .collect(BindingMap.toOrderedMap()))
165             .build()));
166     }
167
168     /*
169      * Replace stateful topology augmentations with ones for rpc in PCEP session
170      * stats data
171      */
172     private static PcepSessionState transformStatefulAugmentation(final PcepSessionState pcepSessionState) {
173         if (pcepSessionState == null) {
174             return null;
175         }
176
177         final PcepSessionStateBuilder sb = new PcepSessionStateBuilder(pcepSessionState);
178
179         final Messages topoMessage = pcepSessionState.getMessages();
180         if (topoMessage != null) {
181             final StatefulMessagesStatsAug messageStatsAug = topoMessage.augmentation(StatefulMessagesStatsAug.class);
182             if (messageStatsAug != null) {
183                 sb.setMessages(new MessagesBuilder(topoMessage)
184                     .removeAugmentation(StatefulMessagesStatsAug.class)
185                         .addAugmentation(new StatefulMessagesRpcAugBuilder()
186                             .setLastReceivedRptMsgTimestamp(messageStatsAug.getLastReceivedRptMsgTimestamp())
187                             .setReceivedRptMsgCount(messageStatsAug.getReceivedRptMsgCount())
188                             .setSentInitMsgCount(messageStatsAug.getSentInitMsgCount())
189                             .setSentUpdMsgCount(messageStatsAug.getSentUpdMsgCount())
190                             .build())
191                         .build());
192             }
193         }
194
195         final PeerCapabilities topoPeerCapability = pcepSessionState.getPeerCapabilities();
196         if (topoPeerCapability != null) {
197             final StatefulCapabilitiesStatsAug capabilityStatsAug =
198                     topoPeerCapability.augmentation(StatefulCapabilitiesStatsAug.class);
199             if (capabilityStatsAug != null) {
200                 sb.setPeerCapabilities(new PeerCapabilitiesBuilder(topoPeerCapability)
201                         .removeAugmentation(StatefulCapabilitiesStatsAug.class)
202                         .addAugmentation(new StatefulCapabilitiesRpcAugBuilder()
203                             .setActive(capabilityStatsAug.getActive())
204                             .setInstantiation(capabilityStatsAug.getInstantiation())
205                             .setStateful(capabilityStatsAug.getStateful())
206                             .build())
207                         .build());
208             }
209         }
210
211         final LocalPref topoLocalPref = pcepSessionState.getLocalPref();
212         if (topoLocalPref != null) {
213             final PcepEntityIdStatsAug entityStatsAug = topoLocalPref.augmentation(PcepEntityIdStatsAug.class);
214             if (entityStatsAug != null) {
215                 sb.setLocalPref(new LocalPrefBuilder(topoLocalPref)
216                     .removeAugmentation(PcepEntityIdStatsAug.class)
217                     .addAugmentation(new PcepEntityIdRpcAugBuilder()
218                             .setSpeakerEntityIdValue(entityStatsAug.getSpeakerEntityIdValue())
219                             .build())
220                     .build());
221             }
222         }
223
224         return sb.build();
225     }
226
227     private List<TopologyId> getAvailableTopologyIds() {
228         return sessionStateMap.keySet().stream().map(iid -> iid.firstKeyOf(Topology.class).getTopologyId()).distinct()
229                 .collect(Collectors.toList());
230     }
231
232     private List<NodeId> getAvailableNodeIds(final TopologyId topologyId) {
233         return sessionStateMap.keySet().stream()
234                 .filter(iid -> iid.firstKeyOf(Topology.class).getTopologyId().equals(topologyId))
235                 .map(iid -> iid.firstKeyOf(Node.class).getNodeId()).collect(Collectors.toList());
236     }
237 }