1 /*******************************************************************************
 
   2  *  ============LICENSE_START=======================================================
 
   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
 
  11  *          http://www.apache.org/licenses/LICENSE-2.0
 
  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=========================================================
 
  20  *******************************************************************************/
 
  21 package org.onap.slice.analysis.ms.service;
 
  23 import java.util.ArrayList;
 
  24 import java.util.HashMap;
 
  25 import java.util.Iterator;
 
  26 import java.util.List;
 
  28 import java.util.Objects;
 
  30 import javax.annotation.PostConstruct;
 
  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;
 
  46  * This class process the measurement data of an S-NSSAI
 
  50 public class SnssaiSamplesProcessor {
 
  51         private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class);
 
  54         private PolicyService policyService;
 
  57         private IConfigDbService configDbService;
 
  60         private PmDataQueue pmDataQueue;
 
  63         private AverageCalculator averageCalculator;
 
  66         private AaiInterface aaiInterface;
 
  69         private CpsInterface cpsInterface;
 
  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;
 
  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();
 
  94          * process the measurement data of an S-NSSAI
 
  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);
 
 110                                 log.info("Not enough samples present for nf {}", nf);
 
 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);
 
 123                         ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai);
 
 124                         ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai);
 
 125                         sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai);
 
 126                         serviceDetails = aaiInterface.fetchServiceDetails(snssai);
 
 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));
 
 137                 updateConfiguration();
 
 138                 if (ricToThroughputMapping.size() > 0) {
 
 139                         AdditionalProperties<Map<String, Map<String, Integer>>> addProps = new AdditionalProperties<>();
 
 140                         addProps.setResourceConfig(ricToThroughputMapping);
 
 141                         policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails);
 
 147          * process the measurement data of an S-NSSAI
 
 149         protected void updateConfiguration() {
 
 150                 Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
 
 151                 Map.Entry<String, Map<String, Integer>> entry = null;
 
 152                 while (it.hasNext()) {
 
 154                         if (entry.getValue().size() == 0) {
 
 160         private void addToMeasurementList(List<MeasurementObject> sample) {
 
 161                 snssaiMeasurementList.addAll(sample);
 
 165          * Calculate the change in the configuration value and keep the configuration
 
 166          * only if it is greater than a specific limit
 
 168         protected void calculatePercentageChange(Map<String, Map<String, Object>> ricConfiguration, String pm) {
 
 169                 Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
 
 170                 Map.Entry<String, Map<String, Integer>> entry = null;
 
 173                 while (it.hasNext()) {
 
 175                         existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm));
 
 176                         change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100;
 
 177                         if (change <= minPercentageChange) {
 
 178                                 ricToThroughputMapping.get(entry.getKey()).remove(pm);
 
 179                                 log.info("Removing pm data {} for RIC {}", pm, entry.getKey());
 
 184         protected void sumOfPrbsAcrossCells(String pmName) {
 
 185                 ricToCellMapping.forEach((ric, cells) -> {
 
 187                         for (String cell : cells) {
 
 188                                 int index = MeasurementObject.findIndex(cell, snssaiMeasurementList);
 
 189                                 sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName);
 
 191                         if (ricToPrbsMapping.containsKey(ric)) {
 
 192                                 ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs);
 
 194                                 Map<String, Integer> pmToPrbMapping = new HashMap<>();
 
 195                                 pmToPrbMapping.put(pmName, sumOfPrbs);
 
 196                                 ricToPrbsMapping.put(ric, pmToPrbMapping);
 
 199                 log.info("PRBs sum computed for RIC {}", ricToPrbsMapping);
 
 202         protected Integer computeSum(String pm) {
 
 203                 return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum);
 
 206         protected void computeThroughput(Map<String, Integer> sliceConfiguration, int sum, String pm) {
 
 207                 Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToPrbsMapping.entrySet().iterator();
 
 208                 Map.Entry<String, Map<String, Integer>> entry = null;
 
 209                 Map<String, Integer> throughtputMap = null;
 
 212                 while (it.hasNext()) {
 
 214                         ric = entry.getKey();
 
 215                         value = Math.round(((float) entry.getValue().get(pm) / sum)
 
 216                                         * (float) sliceConfiguration.get(prbThroughputMapping.get(pm)));
 
 217                         if (ricToThroughputMapping.containsKey(ric)) {
 
 218                                 ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value);
 
 220                                 throughtputMap = new HashMap<>();
 
 221                                 throughtputMap.put(prbThroughputMapping.get(pm), value);
 
 222                                 ricToThroughputMapping.put(ric, throughtputMap);
 
 225                 log.info("Throughput computed for RIC {}", ricToThroughputMapping);