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