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