Fix bug in filtering new FM notification
[dcaegen2/services/son-handler.git] / src / main / java / org / onap / dcaegen2 / services / sonhms / EventHandler.java
1 /*******************************************************************************
2  *  ============LICENSE_START=======================================================
3  *  son-handler
4  *  ================================================================================
5  *   Copyright (C) 2019-2021 Wipro Limited.
6  *   ==============================================================================
7  *     Licensed under the Apache License, Version 2.0 (the "License");
8  *     you may not use this file except in compliance with the License.
9  *     You may obtain a copy of the License at
10  *  
11  *          http://www.apache.org/licenses/LICENSE-2.0
12  *  
13  *     Unless required by applicable law or agreed to in writing, software
14  *     distributed under the License is distributed on an "AS IS" BASIS,
15  *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *     See the License for the specific language governing permissions and
17  *     limitations under the License.
18  *     ============LICENSE_END=========================================================
19  *  
20  *******************************************************************************/
21
22 package org.onap.dcaegen2.services.sonhms;
23
24 import com.fasterxml.jackson.core.JsonProcessingException;
25 import com.fasterxml.jackson.databind.ObjectMapper;
26
27 import fj.data.Either;
28
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.Set;
36 import java.util.concurrent.BlockingQueue;
37 import java.util.concurrent.ExecutorService;
38
39 import org.onap.dcaegen2.services.sonhms.child.ChildThread;
40 import org.onap.dcaegen2.services.sonhms.child.Graph;
41 import org.onap.dcaegen2.services.sonhms.entity.ClusterDetails;
42 import org.onap.dcaegen2.services.sonhms.exceptions.ConfigDbNotFoundException;
43 import org.onap.dcaegen2.services.sonhms.model.CellPciPair;
44 import org.onap.dcaegen2.services.sonhms.model.ClusterMap;
45 import org.onap.dcaegen2.services.sonhms.exceptions.CpsNotFoundException;
46 import org.onap.dcaegen2.services.sonhms.model.FapServiceList;
47 import org.onap.dcaegen2.services.sonhms.model.LteNeighborListInUseLteCell;
48 import org.onap.dcaegen2.services.sonhms.model.Notification;
49 import org.onap.dcaegen2.services.sonhms.utils.ClusterUtils;
50 import org.onap.dcaegen2.services.sonhms.utils.ThreadUtils;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public class EventHandler {
55
56     private static Logger log = LoggerFactory.getLogger(EventHandler.class);
57
58     private static Map<Long, ChildThread> childThreadMap = new HashMap<>();
59
60     private BlockingQueue<List<String>> childStatusQueue;
61
62     private Map<Long, String> childStatus;
63
64     private ExecutorService pool;
65
66     private ClusterUtils clusterUtils;
67
68     private ThreadUtils threadUtils;
69
70     /**
71      * Constructor.
72      */
73     public EventHandler(BlockingQueue<List<String>> childStatusQueue, ExecutorService pool,
74             Map<Long, String> childStatus, ClusterUtils clusterUtils, ThreadUtils threadUtils) {
75
76         this.childStatusQueue = childStatusQueue;
77         this.childStatus = childStatus;
78         this.pool = pool;
79         this.clusterUtils = clusterUtils;
80         this.threadUtils = threadUtils;
81     }
82
83     /**
84      * Handles fault notifications.
85      */
86     public Boolean handleFaultNotification(List<FaultEvent> fmNotification) {
87
88         log.info("Handling Fault notification");
89         log.info("fm notification {}", fmNotification);
90
91         Set<String> cellIds = new HashSet<>();
92         List<ClusterDetails> clusterDetails = clusterUtils.getAllClusters();
93         String networkId = "";
94         Map<String, ArrayList<Integer>> collisionConfusionMap = new HashMap<>();
95         for (FaultEvent faultEvent : fmNotification) {
96             String cellId = faultEvent.getEvent().getCommonEventHeader().getSourceName();
97             cellIds.add(cellId);
98             networkId = faultEvent.getEvent().getFaultFields().getAlarmAdditionalInformation().getNetworkId();
99
100             ArrayList<Integer> counts = new ArrayList<>();
101             counts.add(faultEvent.getEvent().getFaultFields().getEventCategory().contains("PCICollision")?1:0);
102             counts.add(faultEvent.getEvent().getFaultFields().getEventCategory().contains("PCIConfusion")?1:0);
103             collisionConfusionMap.put(cellId, counts);
104         }
105         FaultNotificationtoClusterMapping faultNotificationtoClusterMapping = clusterUtils
106                 .getClustersForFmNotification(cellIds, clusterDetails);
107         faultNotificationtoClusterMapping.setCollisionConfusionMap(collisionConfusionMap);
108
109         // matching cells
110         if (faultNotificationtoClusterMapping.getCellsinCluster() != null 
111                 && !faultNotificationtoClusterMapping.getCellsinCluster().isEmpty()) {
112             try {
113                 handleMatchedFmCells(faultNotificationtoClusterMapping, clusterDetails);
114             } catch (ConfigDbNotFoundException | CpsNotFoundException e) {
115                 log.error("Config DB Exception {} or Cps Exception {} ", e);
116             }
117         }
118         // unmatched new cells
119         if (faultNotificationtoClusterMapping.getNewCells() != null 
120                 && !faultNotificationtoClusterMapping.getNewCells().isEmpty()) {
121            handleUnmatchedFmCells(faultNotificationtoClusterMapping, networkId);
122         }
123
124         return true;
125     }
126
127     /**
128      * handle matched fm cells.
129      * 
130      */
131     private void handleMatchedFmCells(FaultNotificationtoClusterMapping faultNotificationtoClusterMapping,
132             List<ClusterDetails> clusterDetails) throws ConfigDbNotFoundException, CpsNotFoundException {
133         Map<String, String> cellsinCluster = faultNotificationtoClusterMapping.getCellsinCluster();
134         log.info("Handling Matching cells for FM notification");
135
136         for (Entry<String, String> entry : cellsinCluster.entrySet()) {
137
138             String cellId = entry.getKey();
139             String clusterId = entry.getValue();
140             Map<CellPciPair, ArrayList<CellPciPair>> clusterMap = clusterUtils.findClusterMap(cellId);
141
142             Either<ClusterDetails, Integer> clusterDetail = clusterUtils.getClusterDetailsFromClusterId(clusterId,
143                     clusterDetails);
144
145             if (clusterDetail.isRight()) {
146                 log.error("Cannot find the cluster for Cluster ID");
147                 return;
148             } else {
149                 long threadId = clusterDetail.left().value().getChildThreadId();
150
151                 if (childStatus.get(threadId).equals("triggeredOof")) {
152                     log.info("OOF triggered for the cluster, buffering notification");
153                     bufferNotification(clusterMap, clusterId);
154                 } else {
155                     childThreadMap.get(threadId).putInQueue(clusterMap);
156                 }
157             }
158         }
159
160     }
161
162     /**
163      * handle unmatched fm cells.
164      * 
165      */
166     private void handleUnmatchedFmCells(FaultNotificationtoClusterMapping faultNotificationtoClusterMapping,
167             String networkId) {
168         List<String> newCells = faultNotificationtoClusterMapping.getNewCells();
169         log.info("Handle Unmatching cells for FM notificatins newCells{}", newCells);
170         List<Graph> newClusters = new ArrayList<>();
171
172         for (String cellId : newCells) {
173             ArrayList<Integer> collisionConfusionCount = faultNotificationtoClusterMapping.getCollisionConfusionMap()
174                     .get(cellId);
175             log.info("Handle Unmatching cells for FM notificatins,collisionConfusionCount{}", collisionConfusionCount);
176
177             Either<Graph, Integer> existingCluster = clusterUtils.getClusterForFmCell(cellId, newClusters);
178             if (existingCluster.isRight()) {
179                 try {
180                     Map<CellPciPair, ArrayList<CellPciPair>> clusterMap = clusterUtils.findClusterMap(cellId);
181                     Graph cluster = clusterUtils.createCluster(clusterMap);
182                     cluster.setNetworkId(networkId);
183                     Map<String, ArrayList<Integer>> collisionConfusionMap = new HashMap<>();
184                     collisionConfusionMap.put(cellId, collisionConfusionCount);
185                     cluster.setCollisionConfusionMap(collisionConfusionMap);
186
187                     newClusters.add(cluster);
188                 } catch (ConfigDbNotFoundException | CpsNotFoundException e) {
189                     log.error("Error connecting with configDB {}", e);
190                 }
191             }
192
193             else {
194                 Graph cluster = existingCluster.left().value();
195
196                 Graph modifiedCluster = null;
197                 try {
198                     modifiedCluster = clusterUtils.modifyCluster(cluster, clusterUtils.findClusterMap(cellId));
199                     Map<String, ArrayList<Integer>> collisionConfusionMap = cluster.getCollisionConfusionMap();
200                     collisionConfusionMap.put(cellId, collisionConfusionCount);
201                     cluster.setCollisionConfusionMap(collisionConfusionMap);
202                 } catch (ConfigDbNotFoundException | CpsNotFoundException e) {
203                     log.error("Config DB or CPS not found {}", e);
204                 }
205                 newClusters.remove(cluster);
206                 newClusters.add(modifiedCluster);
207             }
208
209         }
210
211         // create new child thread
212         log.info("New clusters {}", newClusters);
213
214         threadUtils.createNewThread(newClusters, childStatusQueue, pool, this, null);
215
216     }
217
218     /**
219      * handle sdnr notification.
220      */
221     public Boolean handleSdnrNotification(Notification notification) {
222         // Check if notification matches with a cluster
223         log.info("Handling SDNR notification");
224         try {
225             List<ClusterDetails> clusterDetails = clusterUtils.getAllClusters();
226
227             NotificationToClusterMapping mapping = clusterUtils.getClustersForNotification(notification,
228                     clusterDetails);
229
230             // Matching cells
231             if (mapping.getCellsinCluster() != null) {
232                 handleMatchingCells(mapping.getCellsinCluster(), clusterDetails);
233             }
234
235             // unmatched cells
236             if (mapping.getNewCells() != null) {
237                 handleUnMatchingCells(mapping.getNewCells());
238             }
239         } catch (Exception e) {
240             log.error("Exception in sdnr notification handling {}", e);
241             return false;
242         }
243
244         return true;
245
246     }
247
248     private void handleUnMatchingCells(List<FapServiceList> newCells) throws ConfigDbNotFoundException, CpsNotFoundException {
249
250         log.info("handling unmatched cells");
251
252         List<Graph> newClusters = new ArrayList<>();
253
254         for (FapServiceList fapService : newCells) {
255
256             Map<CellPciPair, ArrayList<CellPciPair>> clusterMap = clusterUtils.findClusterMap(fapService.getAlias());
257             Either<Graph, Integer> existingCluster = clusterUtils.getClusterForCell(fapService, newClusters);
258             if (existingCluster.isRight()) {
259                 try {
260                     Graph cluster = clusterUtils.createCluster(clusterMap);
261                     cluster.setNetworkId(fapService.getCellConfig().getLte().getRan().getNeighborListInUse()
262                             .getLteNeighborListInUseLteCell().get(0).getPlmnid());
263                     cluster.setCollisionConfusionMap(new HashMap<>());
264                     newClusters.add(cluster);
265                 } catch (ConfigDbNotFoundException | CpsNotFoundException e) {
266                     log.error("Error connecting with configDB {} or CPS {}", e);
267                 }
268             }
269
270             else {
271                 Graph cluster = existingCluster.left().value();
272                 Graph modifiedCluster = clusterUtils.modifyCluster(cluster,
273                         clusterUtils.findClusterMap(fapService.getAlias()));
274                 newClusters.remove(cluster);
275                 newClusters.add(modifiedCluster);
276             }
277
278         }
279
280         // create new child thread
281
282         threadUtils.createNewThread(newClusters, childStatusQueue, pool, this, null);
283
284     }
285
286     private void handleMatchingCells(Map<FapServiceList, String> cellsInCluster, List<ClusterDetails> clusterDetails)
287             throws ConfigDbNotFoundException {
288
289         log.info("handling matching cells");
290
291         for (Entry<FapServiceList, String> entry : cellsInCluster.entrySet()) {
292
293             FapServiceList fapService = entry.getKey();
294             String clusterId = entry.getValue();
295             String cellId = fapService.getAlias();
296             int pci = fapService.getX0005b9Lte().getPhyCellIdInUse();
297             ArrayList<CellPciPair> neighbours = new ArrayList<>();
298             for (LteNeighborListInUseLteCell neighbour : fapService.getCellConfig().getLte().getRan()
299                     .getNeighborListInUse().getLteNeighborListInUseLteCell()) {
300                 String neighbourCellId = neighbour.getAlias();
301                 int neighbourPci = neighbour.getPhyCellId();
302                 neighbours.add(new CellPciPair(neighbourCellId, neighbourPci));
303
304             }
305             Map<CellPciPair, ArrayList<CellPciPair>> clusterMap = new HashMap<>();
306             clusterMap.put(new CellPciPair(cellId, pci), neighbours);
307
308             Either<ClusterDetails, Integer> clusterDetail = clusterUtils.getClusterDetailsFromClusterId(clusterId,
309                     clusterDetails);
310
311             if (clusterDetail.isRight()) {
312                 log.error("Cannot find the cluster for Cluster ID");
313                 return;
314             } else {
315                 long threadId = clusterDetail.left().value().getChildThreadId();
316
317                 if (childStatus.get(threadId).equals("triggeredOof")) {
318                     log.info("OOF triggered for the cluster, buffering notification");
319
320                     bufferNotification(clusterMap, clusterId);
321                 } else {
322                     log.info("Forwarding notification to child thread {}", threadId);
323                     childThreadMap.get(threadId).putInQueue(clusterMap);
324                 }
325             }
326         }
327     }
328
329     private void bufferNotification(Map<CellPciPair, ArrayList<CellPciPair>> clusterMap, String clusterId) {
330
331         log.info("Buffering notifications ...");
332         ObjectMapper mapper = new ObjectMapper();
333         String serviceListString = "";
334
335         ClusterMap clusterMapJson = new ClusterMap();
336
337         clusterMapJson.setCell(clusterMap.keySet().iterator().next());
338         clusterMapJson.setNeighbourList(clusterMap.get(clusterMap.keySet().iterator().next()));
339
340         try {
341             serviceListString = mapper.writeValueAsString(clusterMapJson);
342         } catch (JsonProcessingException e) {
343             log.error("JSON processing exception: {}", e);
344         }
345         BufferNotificationComponent bufferNotifComponent = new BufferNotificationComponent();
346         bufferNotifComponent.bufferNotification(serviceListString, clusterId);
347
348     }
349
350     /**
351      * handle child status update.
352      */
353     public void handleChildStatusUpdate(List<String> childStatus) {
354
355         log.info("Handling child status update");
356
357         Long childThreadId = Long.parseLong(childStatus.get(0));
358         addChildStatus(childThreadId, childStatus.get(1));
359
360         // if child status is OOF result success, handle buffered notifications
361         if (childStatus.get(1).equals("done")) {
362             deleteChildStatus(childThreadId);
363         }
364         // else kill the child thread
365
366     }
367
368     public static void addChildThreadMap(Long childThreadId, ChildThread child) {
369         childThreadMap.put(childThreadId, child);
370     }
371
372     public static Map<Long, ChildThread> getChildThreadMap() {
373         return childThreadMap;
374     }
375
376     public void addChildStatus(Long threadId, String status) {
377         this.childStatus.put(threadId, status);
378     }
379
380     public String getChildStatus(Long threadId) {
381         return childStatus.get(threadId);
382
383     }
384
385     public void deleteChildStatus(Long childThreadId) {
386         this.childStatus.remove(childThreadId);
387
388     }
389
390     public ExecutorService getPool() {
391         return pool;
392     }
393
394 }