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