summaryrefslogtreecommitdiffstats
path: root/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java
diff options
context:
space:
mode:
Diffstat (limited to 'components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java')
-rw-r--r--components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java206
1 files changed, 206 insertions, 0 deletions
diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java
new file mode 100644
index 00000000..874e3271
--- /dev/null
+++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * ============LICENSE_START=======================================================
+ * slice-analysis-ms
+ * ================================================================================
+ * Copyright (C) 2022 Huawei Canada Limited.
+ * ==============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.slice.analysis.ms.service.ccvpn;
+
+import com.google.gson.JsonObject;
+import org.onap.slice.analysis.ms.models.Configuration;
+import org.onap.slice.analysis.ms.service.PolicyService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+@Component
+public class FixedUpperBoundStrategy implements EvaluationStrategy{
+ private static Logger log = LoggerFactory.getLogger(FixedUpperBoundStrategy.class);
+ private Configuration configuration;
+
+ private static final String TYPE_NAME = "FixedUpperBoundStrategy";
+ private static final String SERVICE_INSTANCE_LOCATION_ID = "service-instance-location-id";
+ private static final String BANDWIDTH_TOTAL = "bandwidth-total";
+
+ /**
+ * Percentage threshold of bandwidth adjustment.
+ */
+ private static double threshold;
+
+ /**
+ * Precision of bandwidth evaluation and adjustment.
+ */
+ private static double precision; // in Mbps;
+
+ @Autowired
+ BandwidthEvaluator bandwidthEvaluator;
+
+ @Autowired
+ CCVPNPmDatastore ccvpnPmDatastore;
+
+ @Autowired
+ PolicyService policyService;
+
+ @PostConstruct
+ public void init() {
+ loadConfig();
+ }
+
+ @Override
+ public void execute(Event event){
+ if (event.type() == SimpleEvent.Type.PERIODIC_CHECK && isPeriodicCheckOn()){
+ log.debug("=== Processing new periodic check request: {} ===", event.time());
+ Map<Endpointkey, CCVPNPmDatastore.EvictingQueue<Integer>> usedBwMap = ccvpnPmDatastore.getUsedBwMap();
+ Map<String, Integer> candidate = new TreeMap<>();
+ for(Map.Entry<Endpointkey, CCVPNPmDatastore.EvictingQueue<Integer>> entry: usedBwMap.entrySet()) {
+ String serviceId = entry.getKey().getCllId();
+ Object[] usedBws = entry.getValue().tryReadToArray();
+
+ if (usedBws == null) {
+ // No enough data for evaluating
+ log.debug("CCVPN Evaluator Output: service {}, not enough data to evaluate", serviceId);
+ continue;
+ }
+ if (ccvpnPmDatastore.getProvBwOfSvc(serviceId) == 0) {
+ // Max bandwidth not cached yet
+ log.debug("CCVPN Evaluator Output: service {}, max bandwidth not cached, wait for next round", serviceId);
+ post(new SimpleEvent(SimpleEvent.Type.AAI_BW_REQ, serviceId));
+ continue;
+ }
+ double avg = Arrays.stream(usedBws)
+ .mapToInt(o -> (int) o)
+ .summaryStatistics()
+ .getAverage();
+ int provBw = ccvpnPmDatastore.getProvBwOfSvc(serviceId);
+ int upperBw = ccvpnPmDatastore.getUpperBoundBwOfSvc(serviceId);
+ if (needAdjust(serviceId, avg, provBw, upperBw)) {
+ int newBw = needAdjustTo(serviceId, avg, provBw, upperBw);
+ if(Math.abs(newBw - provBw) >= precision){
+ log.info("CCVPN Evaluator Output: service {}, need adjustment, putting into candidate list", serviceId);
+ candidate.put(serviceId, newBw);
+ }
+ }
+ }
+ // check svc under maintenance
+ Map<String , ServiceState> svcUnderMaintenance = getServicesUnderMaintenance();
+ for (Map.Entry<String, ServiceState> entry: svcUnderMaintenance.entrySet()){
+ candidate.putIfAbsent(entry.getKey(), 0);
+ }
+ // fetch the provisioned bandwidth info if underMaintenance; otherwise send modification request
+ for(Map.Entry<String, Integer> entry: candidate.entrySet()) {
+ //still doing adjustment
+ if (isServiceUnderMaintenance(entry.getKey())) {
+ if (entry.getValue() == 0){
+ log.debug("CCVPN Evaluator Output: service {}," +
+ " is in maintenance state, fetching bandwidth info from AAI", entry.getKey());
+ } else {
+ log.debug("CCVPN Evaluator Output: candidate {}," +
+ " need an adjustment, but skipped due to in maintenance state", entry.getKey());
+ }
+ post(new SimpleEvent(SimpleEvent.Type.AAI_BW_REQ, entry.getKey()));
+ continue;
+ }
+ //not in the mid of adjustment; we are free to adjust.
+ log.info("CCVPN Evaluator Output: candidate {}," +
+ " need an adjustment, sending request to policy", entry.getKey());
+ ccvpnPmDatastore.updateSvcState(entry.getKey(), ServiceState.UNDER_MAINTENANCE);
+ sendModifyRequest(entry.getKey(), entry.getValue(), RequestOwner.DCAE);
+ }
+ log.debug("=== Processing periodic check complete ===");
+ }
+ if (event.type() == SimpleEvent.Type.ONDEMAND_CHECK && isOnDemandCheckOn()) {
+ log.debug("=== Processing upperbound adjustment request: {} ===", event.time());
+ JsonObject payload = (JsonObject) event.subject();
+ String serviceId = payload.get(SERVICE_INSTANCE_LOCATION_ID).getAsString();
+ int newBandwidth = payload.get(BANDWIDTH_TOTAL).getAsInt();
+ log.info("Update service {} bandwidth upperbound to {} ", serviceId, newBandwidth);
+ ccvpnPmDatastore.updateUpperBoundBw(serviceId, newBandwidth);
+ log.debug("=== Processing upperbound adjustment complete ===");
+ }
+ }
+
+ @Override
+ public String getName() {
+ return TYPE_NAME;
+ }
+
+ /**
+ * Post/broadcast event to the BandwidthEvaluator
+ * @param event event object
+ */
+ private void post(Event event){
+ bandwidthEvaluator.post(event);
+ }
+
+ private void loadConfig() {
+ configuration = Configuration.getInstance();
+ threshold = configuration.getCcvpnEvalThreshold();
+ precision = configuration.getCcvpnEvalPrecision(); // in Mbps;
+ }
+
+ private boolean isPeriodicCheckOn() {
+ configuration = Configuration.getInstance();
+ return configuration.isCcvpnEvalPeriodicCheckOn();
+ }
+
+ private boolean isOnDemandCheckOn() {
+ configuration = Configuration.getInstance();
+ return configuration.isCcvpnEvalOnDemandCheckOn();
+ }
+
+ // send modification requestion
+ private void sendModifyRequest(String cllId, Integer newBandwidth, RequestOwner owner) {
+ log.info("Sending modification request to policy. RequestOwner: {} - Service: {} change to bw: {}",
+ owner, cllId, newBandwidth);
+ policyService.sendOnsetMessageToPolicy(
+ policyService.formPolicyOnsetMessageForCCVPN(cllId, newBandwidth, owner)
+ );
+ }
+ // check if an adjustment is necessary
+ private boolean needAdjust(String serivceId, double used, int provBandwidth, int upper){
+ log.debug("CCVPN Service Usage Analysis: usage: {}, threshold: {}, currentProvisioned {}, upperbound {}",
+ used, threshold, provBandwidth, upper);
+ return provBandwidth > upper || used > threshold * provBandwidth;
+ }
+
+ // calculate new bandwidth to accomodate customer
+ private int needAdjustTo(String serivceId, double used, int cur, int upper){
+ if (cur >= upper){
+ return upper;
+ }
+ int expected = (int) (Math.ceil((used / threshold) * 1.2 / precision) * precision);
+ return Math.min(expected, upper);
+ }
+ // check is service under maint
+ private boolean isServiceUnderMaintenance(String serivceId) {
+ return ccvpnPmDatastore.getStatusOfSvc(serivceId) == ServiceState.UNDER_MAINTENANCE;
+ }
+ // get a collection of service under maint
+ private Map<String, ServiceState> getServicesUnderMaintenance(){
+ return ccvpnPmDatastore.getSvcStatusMap().entrySet()
+ .stream()
+ .filter(e -> e.getValue() == ServiceState.UNDER_MAINTENANCE)
+ .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
+ }
+}