org.openbaton.autoscaling.core.features.pool.PoolManagement.java Source code

Java tutorial

Introduction

Here is the source code for org.openbaton.autoscaling.core.features.pool.PoolManagement.java

Source

/*
 *
 *  * (C) Copyright 2016 NUBOMEDIA (http://www.nubomedia.eu)
 *  *
 *  * 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.
 *  *
 *
 */

package org.openbaton.autoscaling.core.features.pool;

import org.openbaton.autoscaling.catalogue.Action;
import org.openbaton.autoscaling.core.features.pool.task.PoolTask;
import org.openbaton.autoscaling.core.management.ASBeanConfiguration;
import org.openbaton.autoscaling.core.management.ActionMonitor;
import org.openbaton.catalogue.mano.descriptor.VirtualDeploymentUnit;
import org.openbaton.catalogue.mano.record.NetworkServiceRecord;
import org.openbaton.catalogue.mano.record.VNFCInstance;
import org.openbaton.catalogue.mano.record.VirtualNetworkFunctionRecord;
import org.openbaton.exceptions.NotFoundException;
import org.openbaton.exceptions.VimException;
import org.openbaton.sdk.NFVORequestor;
import org.openbaton.sdk.api.exception.SDKException;
import org.openbaton.vnfm.configuration.NfvoProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.util.ErrorHandler;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;

/**
 * Created by mpa on 27.10.15.
 */
@Service
@Scope("singleton")
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { ASBeanConfiguration.class })
public class PoolManagement {

    protected Logger log = LoggerFactory.getLogger(this.getClass());

    private ThreadPoolTaskScheduler taskScheduler;

    private Map<String, ScheduledFuture> poolTasks;

    @Autowired
    private NFVORequestor nfvoRequestor;

    private Map<String, Map<String, Map<String, Set<VNFCInstance>>>> reservedInstances;

    private ActionMonitor actionMonitor;

    @Autowired
    private PoolEngine poolEngine;

    @Autowired
    private NfvoProperties nfvoProperties;

    @Value("${autoscaling.pool.size}")
    private int POOL_SIZE;

    @Value("${autoscaling.pool.period}")
    private int POOL_CHECK_PERIOD;

    @Value("${autoscaling.pool.prepare}")
    private boolean POOL_PREPARE;

    @PostConstruct
    public void init() throws SDKException {
        this.actionMonitor = new ActionMonitor();
        this.poolTasks = new HashMap<>();
        this.taskScheduler = new ThreadPoolTaskScheduler();
        this.taskScheduler.setPoolSize(10);
        this.taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        this.taskScheduler.setRemoveOnCancelPolicy(true);
        this.taskScheduler.setErrorHandler(new ErrorHandler() {
            protected Logger log = LoggerFactory.getLogger(this.getClass());

            @Override
            public void handleError(Throwable t) {
                log.error(t.getMessage(), t);
            }
        });
        this.taskScheduler.initialize();

        reservedInstances = new HashMap<>();
    }

    public void activate(String nsr_id) throws NotFoundException {
        log.debug("Activating pool mechanism for NSR " + nsr_id);
        log.info("AutoScaling: Pool Size for nsr with: " + nsr_id + " -> " + POOL_SIZE);
        NetworkServiceRecord nsr = null;
        try {
            nsr = nfvoRequestor.getNetworkServiceRecordAgent().findById(nsr_id);
        } catch (SDKException e) {
            log.error(e.getMessage(), e);
        } catch (ClassNotFoundException e) {
            log.error(e.getMessage(), e);
        }
        if (nsr == null) {
            throw new NotFoundException("Not Found NetworkServiceDescriptor with id: " + nsr_id);
        }
        //Prepare data structure
        Map<String, Map<String, Set<VNFCInstance>>> vnfrMap;
        if (reservedInstances.containsKey(nsr_id)) {
            vnfrMap = reservedInstances.get(nsr_id);
        } else {
            vnfrMap = new HashMap<String, Map<String, Set<VNFCInstance>>>();
        }
        for (VirtualNetworkFunctionRecord vnfr : nsr.getVnfr()) {
            Map<String, Set<VNFCInstance>> vduMap;
            if (vnfrMap.containsKey(vnfr.getId())) {
                vduMap = vnfrMap.get(vnfr.getId());
            } else {
                vduMap = new HashMap<String, Set<VNFCInstance>>();
            }
            for (VirtualDeploymentUnit vdu : vnfr.getVdu()) {
                Set<VNFCInstance> vnfcInstances;
                if (vduMap.containsKey(vdu.getId())) {
                    vnfcInstances = vduMap.get(vdu.getId());
                } else {
                    vnfcInstances = new HashSet<>();
                }
                if (POOL_PREPARE == true) {
                    for (int i = 1; i <= POOL_SIZE; i++) {
                        VNFCInstance vnfcInstance = poolEngine.allocateNewInstance(nsr_id, vnfr, vdu);
                        if (vnfcInstance != null) {
                            vnfcInstances.add(vnfcInstance);
                        }
                    }
                }
                vduMap.put(vdu.getId(), vnfcInstances);
            }
            vnfrMap.put(vnfr.getId(), vduMap);
        }
        reservedInstances.put(nsr_id, vnfrMap);
        startPoolCheck(nsr_id);
    }

    public void activate(String nsr_id, String vnfr_id) throws NotFoundException {
        log.debug("Activating pool mechanism for VNFR " + vnfr_id);
        log.info("Pool Size for VNFR with id: " + vnfr_id + " -> " + POOL_SIZE);
        VirtualNetworkFunctionRecord vnfr = null;
        try {
            vnfr = nfvoRequestor.getNetworkServiceRecordAgent().getVirtualNetworkFunctionRecord(nsr_id, vnfr_id);
        } catch (SDKException e) {
            log.error(e.getMessage(), e);
        }
        if (vnfr == null) {
            throw new NotFoundException("Not Found VirtualNetworkFunctionRecord with id: " + vnfr_id);
        }
        //Prepare data structure
        Map<String, Map<String, Set<VNFCInstance>>> vnfrMap;
        if (reservedInstances.containsKey(nsr_id)) {
            vnfrMap = reservedInstances.get(nsr_id);
        } else {
            vnfrMap = new HashMap<String, Map<String, Set<VNFCInstance>>>();
        }
        Map<String, Set<VNFCInstance>> vduMap;
        if (vnfrMap.containsKey(vnfr_id)) {
            vduMap = vnfrMap.get(vnfr_id);
        } else {
            vduMap = new HashMap<String, Set<VNFCInstance>>();
        }
        for (VirtualDeploymentUnit vdu : vnfr.getVdu()) {
            Set<VNFCInstance> vnfcInstances;
            if (vduMap.containsKey(vdu.getId())) {
                vnfcInstances = vduMap.get(vdu.getId());
            } else {
                vnfcInstances = new HashSet<>();
            }
            if (POOL_PREPARE == true) {
                log.info("Preparing pool for VNFR with id: " + vnfr_id);
                Set<VNFCInstance> vnfcInstances_new = poolEngine.allocateNewInstance(nsr_id, vnfr, vdu, POOL_SIZE);
                if (vnfcInstances_new != null) {
                    vnfcInstances.addAll(vnfcInstances_new);
                }
            }
            vduMap.put(vdu.getId(), vnfcInstances);
        }
        vnfrMap.put(vnfr.getId(), vduMap);
        reservedInstances.put(nsr_id, vnfrMap);
        startPoolCheck(nsr_id);
    }

    public void deactivate(String nsr_id) throws NotFoundException, VimException {
        log.debug("Deactivating pool mechanism for NSR " + nsr_id);
        stopPoolCheck(nsr_id);
        poolEngine.releaseReservedInstances(nsr_id);
        log.info("Deactivated pool mechanism for NSR " + nsr_id);
    }

    @Async
    public Future<Boolean> deactivate(String nsr_id, String vnfr_id) throws NotFoundException, VimException {
        log.debug("Deactivating pool mechanism for NSR " + nsr_id);
        if (reservedInstances.containsKey(nsr_id)) {
            if (reservedInstances.get(nsr_id).size() == 1) {
                try {
                    stopPoolCheck(nsr_id).get();
                } catch (InterruptedException e) {
                    log.error(e.getMessage(), e);
                    return new AsyncResult<Boolean>(false);
                } catch (ExecutionException e) {
                    log.error(e.getMessage(), e);
                    return new AsyncResult<Boolean>(false);
                }
            }
        }
        poolEngine.releaseReservedInstances(nsr_id, vnfr_id);
        log.info("Deactivated pool mechanism for NSR " + nsr_id);
        return new AsyncResult<Boolean>(true);
    }

    public Map<String, Map<String, Set<VNFCInstance>>> getReservedInstances(String nsr_id) {
        if (reservedInstances.containsKey(nsr_id)) {
            if (reservedInstances.get(nsr_id) != null) {
                return reservedInstances.get(nsr_id);
            }
        } else {
            log.warn("Not found any reserved VNFCInstance for NSR with id: " + nsr_id);
        }
        return new HashMap<>();
    }

    public VNFCInstance getReservedInstance(String nsr_id, String vnfr_id, String vdu_id) {
        VNFCInstance returnedInstance = null;
        if (!getReservedInstances(nsr_id).isEmpty()) {
            if (getReservedInstances(nsr_id).containsKey(vnfr_id)) {
                if (getReservedInstances(nsr_id).get(vnfr_id).containsKey(vdu_id)) {
                    if (getReservedInstances(nsr_id).get(vnfr_id).get(vdu_id).iterator().hasNext()) {
                        returnedInstance = getReservedInstances(nsr_id).get(vnfr_id).get(vdu_id).iterator().next();
                        getReservedInstances(nsr_id).get(vnfr_id).get(vdu_id).remove(returnedInstance);
                    } else {
                        //Allocate new Instance if no one was found
                        //returnedInstance = poolEngine.allocateNewInstance(nsr_id, vnfr_id, vdu_id);
                        log.warn("No VNFCInstances left in pool for VDU with id: " + vdu_id);
                    }
                } else {
                    log.warn("Reserved instances for VDU with id: " + vdu_id + " were not initialized properly");
                }
            } else {
                log.warn("Reserved instances for VNFR with id: " + vnfr_id + " were not initialized properly");
            }
        } else {
            log.warn("Reserved instances for NSR with id: " + nsr_id + " were not initialized properly");
        }
        return returnedInstance;
    }

    public void removeReservedInstances(String nsr_id) {
        reservedInstances.remove(nsr_id);
    }

    public void startPoolCheck(String nsr_id) throws NotFoundException {
        log.debug("Activating Pool size checking for NSR with id: " + nsr_id);
        if (!poolTasks.containsKey(nsr_id)) {
            log.debug("Creating new PoolTask for NSR with id: " + nsr_id);
            actionMonitor.requestAction(nsr_id, Action.INACTIVE);
            PoolTask poolTask = new PoolTask(nsr_id, POOL_SIZE, poolEngine, actionMonitor);
            ScheduledFuture scheduledFuture = taskScheduler.scheduleAtFixedRate(poolTask, POOL_CHECK_PERIOD * 1000);
            log.debug("Activated Pool size checking for NSR with id: " + nsr_id);
            poolTasks.put(nsr_id, scheduledFuture);
        } else {
            log.debug("Pool size checking of NSR with id: " + nsr_id + " were already activated");
        }
    }

    @Async
    public Future<Boolean> stopPoolCheck(String nsr_id) {
        log.debug("Deactivating Pool size checking for NSR with id: " + nsr_id);
        if (poolTasks.containsKey(nsr_id)) {
            poolTasks.get(nsr_id).cancel(false);
            int i = 60;
            while (!actionMonitor.isTerminated(nsr_id) && actionMonitor.getAction(nsr_id) != Action.INACTIVE
                    && i >= 0) {
                actionMonitor.terminate(nsr_id);
                log.debug("Waiting for finishing gracefully PoolTask for NSR with id: " + nsr_id + " (" + i + "s)");
                log.debug(actionMonitor.toString());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log.error(e.getMessage(), e);
                }
                i--;
                if (i <= 0) {
                    actionMonitor.removeId(nsr_id);
                    log.error("Forced deactivation of poolTask for NSR with id: " + nsr_id);
                    poolTasks.get(nsr_id).cancel(true);
                    poolTasks.remove(nsr_id);
                    return new AsyncResult<>(false);
                }
            }
            poolTasks.remove(nsr_id);
            actionMonitor.removeId(nsr_id);
            log.debug("Deactivated Pool size checking for NSR with id: " + nsr_id);
        } else {
            log.debug("Not Found PoolTask for NSR with id: " + nsr_id);
        }
        return new AsyncResult<>(true);
    }
}