e8d5de3e693df8dca4dcca29795bda6761ea468b
[dcaegen2/services.git] /
1 /*******************************************************************************
2  *  ============LICENSE_START=======================================================
3  *  slice-analysis-ms
4  *  ================================================================================
5  *   Copyright (C) 2020 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 package org.onap.slice.analysis.ms.service;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.annotation.PostConstruct;
30
31 import org.onap.slice.analysis.ms.configdb.IConfigDbService;
32 import org.onap.slice.analysis.ms.models.Configuration;
33 import org.onap.slice.analysis.ms.models.MeasurementObject;
34 import org.onap.slice.analysis.ms.models.SubCounter;
35 import org.onap.slice.analysis.ms.models.policy.AdditionalProperties;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38 import org.springframework.beans.factory.annotation.Autowired;
39 import org.springframework.context.annotation.Scope;
40 import org.springframework.stereotype.Component;
41
42 /** 
43  * This class process the measurement data of an S-NSSAI
44  */
45 @Component
46 @Scope("prototype")
47 public class SnssaiSamplesProcessor {
48         private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class);
49
50         @Autowired
51         private PolicyService policyService;
52         
53         @Autowired
54         private IConfigDbService configDbService;
55         
56         @Autowired
57         private PmDataQueue pmDataQueue;
58         
59         @Autowired
60         private AverageCalculator averageCalculator;
61         
62         private List<MeasurementObject> snssaiMeasurementList = new ArrayList<>();
63         private Map<String, List<String>> ricToCellMapping = new HashMap<>();
64         private Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>();
65         private Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>();
66         private int noOfSamples;
67         private List<String> pmsToCompute;      
68         private Map<String, String> prbThroughputMapping = new HashMap<>(); 
69         private int minPercentageChange;
70         
71         @PostConstruct
72         public void init() {
73                 Configuration configuration = Configuration.getInstance();
74                 noOfSamples = configuration.getSamples();
75                 pmsToCompute = new ArrayList<>();
76                 pmsToCompute.add("PrbUsedDl");
77                 pmsToCompute.add("PrbUsedUl");
78                 prbThroughputMapping = new HashMap<>();
79                 prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice");
80                 prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice");
81                 minPercentageChange = configuration.getMinPercentageChange();
82         }
83
84         /**
85          * process the measurement data of an S-NSSAI
86          */
87         public boolean processSamplesOfSnnsai(String snssai, List<String> networkFunctions) { 
88                 List<MeasurementObject> sample = null;
89                 List<List<MeasurementObject>> samples = null;
90                 log.info("Network Functions {} of snssai {}", networkFunctions, snssai);
91                 for(String nf : networkFunctions) {
92                         log.debug("Average of samples for {}:", snssai);
93                         samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples);
94                         if(samples != null) {
95                                 sample = averageCalculator.findAverageOfSamples(samples);
96                                 addToMeasurementList(sample);
97                         }
98                         else {
99                                 log.info("Not enough samples present for nf {}", nf);
100                                 return false;
101                         }
102                 }               
103                 log.info("snssai measurement list {}", snssaiMeasurementList);
104                 ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai);   
105                 log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping);
106                 Map<String, Map<String, Object>> ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai);
107                 Map<String, Integer> sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai);
108                 log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration);
109                 pmsToCompute.forEach(pm -> {
110                         log.debug("processing for pm {}", pm);
111                         sumOfPrbsAcrossCells(pm);
112                         int sum = computeSum(pm);
113                         computeThroughput(sliceConfiguration, sum, pm);
114                         calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm));
115                 });
116                 updateConfiguration();  
117                 if(ricToThroughputMapping.size() > 0) {
118                         AdditionalProperties<Map<String, Map<String, Integer>>> addProps = new AdditionalProperties<>();
119                         addProps.setResourceConfig(ricToThroughputMapping);
120                         policyService.sendOnsetMessageToPolicy(snssai, addProps, configDbService.fetchServiceDetails(snssai));
121                 }
122                 return true;
123         }
124
125         /**
126          * process the measurement data of an S-NSSAI
127          */
128         protected void updateConfiguration() {
129                 Iterator<Map.Entry<String, Map<String,Integer>>> it = ricToThroughputMapping.entrySet().iterator();
130                 Map.Entry<String, Map<String,Integer>> entry = null;
131                 while(it.hasNext()) {
132                         entry = it.next();
133                         if(entry.getValue().size() == 0) {
134                                 it.remove();
135                         }
136                 }
137         }
138
139         private void addToMeasurementList(List<MeasurementObject> sample) {
140                 snssaiMeasurementList.addAll(sample);
141         }
142
143         /**
144          * Calculate the change in the configuration value and keep the configuration only if it is greater than a
145          * specific limit 
146          */
147         protected void calculatePercentageChange(Map<String, Map<String, Object>> ricConfiguration, String pm) {
148                 Iterator<Map.Entry<String, Map<String,Integer>>> it = ricToThroughputMapping.entrySet().iterator();
149                 Map.Entry<String, Map<String,Integer>> entry = null;
150                 float existing = 0;
151                 float change = 0;
152                 while(it.hasNext()) {
153                         entry = it.next();
154                         existing = (float)((int)ricConfiguration.get(entry.getKey()).get(pm));
155                         change = ((Math.abs(entry.getValue().get(pm) - existing))/existing)*100;
156                         if (change <= minPercentageChange) {
157                                 ricToThroughputMapping.get(entry.getKey()).remove(pm);
158                                 log.info("Removing pm data {} for RIC {}", pm, entry.getKey());
159                         }
160                 }
161         }
162         
163         protected void sumOfPrbsAcrossCells(String pmName) {
164                 ricToCellMapping.forEach((ric,cells) -> {
165                         int sumOfPrbs = 0;
166                         for(String cell : cells) {
167                                 int index = MeasurementObject.findIndex(cell, snssaiMeasurementList);
168                                 sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName);
169                         }
170                         if(ricToPrbsMapping.containsKey(ric)) {
171                                 ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs);
172                         }
173                         else {
174                                 Map<String, Integer> pmToPrbMapping  = new HashMap<>();
175                                 pmToPrbMapping.put(pmName, sumOfPrbs);
176                                 ricToPrbsMapping.put(ric, pmToPrbMapping);
177                         }
178                 });
179                 log.info("PRBs sum computed for RIC {}", ricToPrbsMapping);
180         }
181
182         protected Integer computeSum(String pm) {
183                 return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum);
184         }
185
186         protected void computeThroughput(Map<String, Integer> sliceConfiguration, int sum, String pm) {
187                 Iterator<Map.Entry<String, Map<String,Integer>>> it = ricToPrbsMapping.entrySet().iterator();
188                 Map.Entry<String, Map<String,Integer>> entry = null;
189                 Map<String, Integer> throughtputMap = null;
190                 String ric = "";
191                 int value = 0;
192                 while(it.hasNext()) {
193                         entry = it.next();
194                         ric = entry.getKey();
195                         value = Math.round(((float)entry.getValue().get(pm)/sum)*(float)sliceConfiguration.get(prbThroughputMapping.get(pm)));
196                         if(ricToThroughputMapping.containsKey(ric)) {
197                                 ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value);
198                         }
199                         else {
200                                 throughtputMap = new HashMap<>();
201                                 throughtputMap.put(prbThroughputMapping.get(pm), value);
202                                 ricToThroughputMapping.put(ric, throughtputMap);
203                         }
204                 }
205                 log.info("Throughput computed for RIC {}", ricToThroughputMapping);
206         }
207 }