org.openbaton.vnfm.generic.GenericVNFM.java Source code

Java tutorial

Introduction

Here is the source code for org.openbaton.vnfm.generic.GenericVNFM.java

Source

/*
 * Copyright (c) 2016 Open Baton (http://www.openbaton.org)
 *
 * 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.vnfm.generic;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;

import org.apache.commons.codec.binary.Base64;
import org.openbaton.catalogue.mano.common.Event;
import org.openbaton.catalogue.mano.common.Ip;
import org.openbaton.catalogue.mano.common.LifecycleEvent;
import org.openbaton.catalogue.mano.descriptor.VNFComponent;
import org.openbaton.catalogue.mano.descriptor.VirtualDeploymentUnit;
import org.openbaton.catalogue.mano.record.VNFCInstance;
import org.openbaton.catalogue.mano.record.VNFRecordDependency;
import org.openbaton.catalogue.mano.record.VirtualNetworkFunctionRecord;
import org.openbaton.catalogue.nfvo.Action;
import org.openbaton.catalogue.nfvo.ConfigurationParameter;
import org.openbaton.catalogue.nfvo.DependencyParameters;
import org.openbaton.catalogue.nfvo.Script;
import org.openbaton.catalogue.nfvo.VNFCDependencyParameters;
import org.openbaton.catalogue.nfvo.VimInstance;
import org.openbaton.common.vnfm_sdk.AbstractVnfm;
import org.openbaton.common.vnfm_sdk.amqp.AbstractVnfmSpringAmqp;
import org.openbaton.common.vnfm_sdk.exception.VnfmSdkException;
import org.openbaton.common.vnfm_sdk.interfaces.EmsRegistrator;
import org.openbaton.common.vnfm_sdk.utils.VnfmUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

/**
 * Created by mob on 16.07.15.
 */
@EnableScheduling
public class GenericVNFM extends AbstractVnfmSpringAmqp {

    @Autowired
    private EmsRegistrator emsRegistrator;
    private Gson parser = new GsonBuilder().setPrettyPrinting().create();
    private String scriptPath;

    @Value("${vnfm.ems.start.timeout:500}")
    private int waitForEms;

    @Value("${vnfm.ems.script.logpath:/var/log/openbaton/scriptsLog/}")
    private String scriptsLogPath;

    @Value("${vnfm.ems.script.old:60}")
    private int old;

    public static void main(String[] args) {
        SpringApplication.run(GenericVNFM.class, args);
    }

    private static String convertStreamToString(InputStream is) {
        Scanner s = new Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }

    @Override
    public VirtualNetworkFunctionRecord instantiate(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            Object scripts, Map<String, Collection<VimInstance>> vimInstances) throws Exception {

        log.info("Instantiation of VirtualNetworkFunctionRecord " + virtualNetworkFunctionRecord.getName());
        if (null != scripts) {
            this.saveScriptOnEms(virtualNetworkFunctionRecord, scripts);
        }

        for (VirtualDeploymentUnit virtualDeploymentUnit : virtualNetworkFunctionRecord.getVdu()) {
            for (VNFCInstance vnfcInstance : virtualDeploymentUnit.getVnfc_instance()) {
                log.debug("VNFCInstance: " + vnfcInstance);
            }
        }

        String output = "\n--------------------\n--------------------\n";
        for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, Event.INSTANTIATE)) {
            output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString().replaceAll("\\\\n",
                    "\n");
            output += "\n--------------------\n";
        }
        output += "\n--------------------\n";
        log.info("Executed script for INSTANTIATE. Output was: \n\n" + output);
        return virtualNetworkFunctionRecord;
    }

    @Override
    public void query() {
    }

    @Override
    public VirtualNetworkFunctionRecord scale(Action scaleInOrOut,
            VirtualNetworkFunctionRecord virtualNetworkFunctionRecord, VNFComponent component, Object scripts,
            VNFRecordDependency dependency) throws Exception {
        VNFCInstance vnfcInstance = (VNFCInstance) component;
        if (scaleInOrOut.ordinal() == Action.SCALE_OUT.ordinal()) {
            log.info("Created VNFComponent");
            saveScriptOnEms(vnfcInstance, scripts, virtualNetworkFunctionRecord);
            String output = "\n--------------------\n--------------------\n";
            for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, vnfcInstance,
                    Event.INSTANTIATE)) {
                output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                        .replaceAll("\\\\n", "\n");
                output += "\n--------------------\n";
            }
            output += "\n--------------------\n";
            log.info("Executed script for INSTANTIATE. Output was: \n\n" + output);

            if (dependency != null) {
                output = "\n--------------------\n--------------------\n";
                for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, vnfcInstance,
                        Event.CONFIGURE, dependency)) {
                    output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                            .replaceAll("\\\\n", "\n");
                    output += "\n--------------------\n";
                }
                output += "\n--------------------\n";
                log.info("Executed script for CONFIGURE. Output was: \n\n" + output);
            }

            if ((vnfcInstance.getState() == null) || !vnfcInstance.getState().equals("STANDBY")) {
                if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(),
                        Event.START) != null) {
                    output = "\n--------------------\n--------------------\n";
                    for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, vnfcInstance,
                            Event.START)) {
                        output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                                .replaceAll("\\\\n", "\n");
                        output += "\n--------------------\n";
                    }
                    output += "\n--------------------\n";
                    log.info("Executed script for START. Output was: \n\n" + output);
                }
            }

            log.trace("HB_VERSION == " + virtualNetworkFunctionRecord.getHb_version());
            return virtualNetworkFunctionRecord;
        } else { // SCALE_IN

            String output = "\n--------------------\n--------------------\n";
            for (String result : executeScriptsForEventOnVnfr(virtualNetworkFunctionRecord, vnfcInstance,
                    Event.SCALE_IN)) {
                output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                        .replaceAll("\\\\n", "\n");
                output += "\n--------------------\n";
            }
            output += "\n--------------------\n";
            log.info("Executed script for SCALE_IN. Output was: \n\n" + output);

            return virtualNetworkFunctionRecord;
        }
    }

    private Iterable<? extends String> executeScriptsForEventOnVnfr(
            VirtualNetworkFunctionRecord virtualNetworkFunctionRecord, VNFCInstance vnfcInstanceRemote, Event event)
            throws Exception {
        Map<String, String> env = getMap(virtualNetworkFunctionRecord);
        Collection<String> res = new ArrayList<>();
        LifecycleEvent le = VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), event);
        if (le != null) {
            log.trace("The number of scripts for " + virtualNetworkFunctionRecord.getName() + " are: "
                    + le.getLifecycle_events());
            for (VirtualDeploymentUnit virtualDeploymentUnit : virtualNetworkFunctionRecord.getVdu()) {
                for (VNFCInstance vnfcInstanceLocal : virtualDeploymentUnit.getVnfc_instance()) {
                    for (String script : le.getLifecycle_events()) {
                        log.info("Sending script: " + script + " to VirtualNetworkFunctionRecord: "
                                + virtualNetworkFunctionRecord.getName() + " on VNFCInstance: "
                                + vnfcInstanceLocal.getId());
                        Map<String, String> tempEnv = new HashMap<>();
                        for (Ip ip : vnfcInstanceLocal.getIps()) {
                            log.debug("Adding net: " + ip.getNetName() + " with value: " + ip.getIp());
                            tempEnv.put(ip.getNetName(), ip.getIp());
                        }
                        log.debug("adding floatingIp: " + vnfcInstanceLocal.getFloatingIps());
                        for (Ip fip : vnfcInstanceLocal.getFloatingIps()) {
                            tempEnv.put(fip.getNetName() + "_floatingIp", fip.getIp());
                        }

                        tempEnv.put("hostname", vnfcInstanceLocal.getHostname());

                        if (vnfcInstanceRemote != null) {
                            //TODO what should i put here?
                            for (Ip ip : vnfcInstanceRemote.getIps()) {
                                log.debug("Adding net: " + ip.getNetName() + " with value: " + ip.getIp());
                                tempEnv.put("removing_" + ip.getNetName(), ip.getIp());
                            }
                            log.debug("adding floatingIp: " + vnfcInstanceRemote.getFloatingIps());
                            for (Ip fip : vnfcInstanceRemote.getFloatingIps()) {
                                tempEnv.put("removing_" + fip.getNetName() + "_floatingIp", fip.getIp());
                            }

                            tempEnv.put("removing_" + "hostname", vnfcInstanceRemote.getHostname());
                        }

                        tempEnv = modifyUnsafeEnvVarNames(tempEnv);
                        env.putAll(tempEnv);
                        log.info("The Environment Variables for script " + script + " are: " + env);

                        String command = getJsonObject("EXECUTE", script, env).toString();
                        String output = executeActionOnEMS(vnfcInstanceLocal.getHostname(), command,
                                virtualNetworkFunctionRecord, vnfcInstanceLocal);
                        res.add(output);

                        saveLogToFile(virtualNetworkFunctionRecord, script, vnfcInstanceLocal, output);
                        for (String key : tempEnv.keySet()) {
                            env.remove(key);
                        }
                    }
                }
            }
        }
        return res;
    }

    private Map<String, String> modifyUnsafeEnvVarNames(Map<String, String> env) {

        Map<String, String> result = new HashMap<>();

        for (Entry<String, String> entry : env.entrySet()) {
            result.put(entry.getKey().replaceAll("[^A-Za-z0-9_]", "_"), entry.getValue());
        }

        return result;
    }

    private Iterable<String> executeScriptsForEvent(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance vnfcInstance, Event event) throws Exception {
        Map<String, String> env = getMap(virtualNetworkFunctionRecord);
        List<String> res = new ArrayList<>();
        LifecycleEvent le = VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), event);

        if (le != null) {
            log.trace("The number of scripts for " + virtualNetworkFunctionRecord.getName() + " are: "
                    + le.getLifecycle_events());
            for (String script : le.getLifecycle_events()) {
                log.info("Sending script: " + script + " to VirtualNetworkFunctionRecord: "
                        + virtualNetworkFunctionRecord.getName());
                Map<String, String> tempEnv = new HashMap<>();
                for (Ip ip : vnfcInstance.getIps()) {
                    log.debug("Adding net: " + ip.getNetName() + " with value: " + ip.getIp());
                    tempEnv.put(ip.getNetName(), ip.getIp());
                }
                log.debug("adding floatingIp: " + vnfcInstance.getFloatingIps());
                for (Ip fip : vnfcInstance.getFloatingIps()) {
                    tempEnv.put(fip.getNetName() + "_floatingIp", fip.getIp());
                }

                tempEnv.put("hostname", vnfcInstance.getHostname());

                tempEnv = modifyUnsafeEnvVarNames(tempEnv);
                env.putAll(tempEnv);
                log.info("The Environment Variables for script " + script + " are: " + env);

                String command = getJsonObject("EXECUTE", script, env).toString();
                if (event.ordinal() == Event.SCALE_IN.ordinal()) {
                    for (VirtualDeploymentUnit vdu : virtualNetworkFunctionRecord.getVdu()) {
                        for (VNFCInstance vnfcInstance1 : vdu.getVnfc_instance()) {

                            String output = executeActionOnEMS(vnfcInstance1.getHostname(), command,
                                    virtualNetworkFunctionRecord, vnfcInstance);
                            res.add(output);
                            saveLogToFile(virtualNetworkFunctionRecord, script, vnfcInstance1, output);
                        }
                    }
                } else {
                    res.add(executeActionOnEMS(vnfcInstance.getHostname(), command, virtualNetworkFunctionRecord,
                            vnfcInstance));
                }

                for (String key : tempEnv.keySet()) {
                    env.remove(key);
                }
            }
        }
        return res;
    }

    private void saveLogToFile(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord, String script,
            VNFCInstance vnfcInstance1, String output) throws IOException {
        saveLogToFile(virtualNetworkFunctionRecord, script, vnfcInstance1, output, false);
    }

    private void saveLogToFile(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord, String script,
            VNFCInstance vnfcInstance1, String output, boolean error) throws IOException {
        if (this.old > 0) {
            String path = "";
            if (!error) {
                path = this.scriptsLogPath + virtualNetworkFunctionRecord.getName() + "/"
                        + vnfcInstance1.getHostname() + ".log";
            } else {
                path = this.scriptsLogPath + virtualNetworkFunctionRecord.getName() + "/"
                        + vnfcInstance1.getHostname() + "-error.log";
            }
            File f = new File(path);

            if (!f.exists()) {
                f.getParentFile().mkdirs();
                f.createNewFile();
            }

            if (!error) {
                Files.write(Paths.get(path), ("Output of Script : " + script + "\n\n").getBytes(),
                        StandardOpenOption.APPEND);
                Files.write(Paths.get(path), this.parser.fromJson(output, JsonObject.class).get("output")
                        .getAsString().replaceAll("\\\\n", "\n").getBytes(), StandardOpenOption.APPEND);
            } else {
                Files.write(Paths.get(path), ("Error log of Script : " + script + "\n\n").getBytes(),
                        StandardOpenOption.APPEND);
                Files.write(Paths.get(path), this.parser.fromJson(output, JsonObject.class).get("err").getAsString()
                        .replaceAll("\\\\n", "\n").getBytes(), StandardOpenOption.APPEND);
            }
            Files.write(Paths.get(path),
                    "\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~\n#########################\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\n\n"
                            .getBytes(),
                    StandardOpenOption.APPEND);
        }
    }

    private Iterable<String> executeScriptsForEvent(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance vnfcInstance, Event event, String cause) throws Exception {
        Map<String, String> env = getMap(virtualNetworkFunctionRecord);
        List<String> res = new LinkedList<>();
        LifecycleEvent le = VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), event);

        if (le != null) {
            log.trace("The number of scripts for " + virtualNetworkFunctionRecord.getName() + " are: "
                    + le.getLifecycle_events());
            for (String script : le.getLifecycle_events()) {
                log.info("Sending script: " + script + " to VirtualNetworkFunctionRecord: "
                        + virtualNetworkFunctionRecord.getName());
                Map<String, String> tempEnv = new HashMap<>();
                for (Ip ip : vnfcInstance.getIps()) {
                    log.debug("Adding net: " + ip.getNetName() + " with value: " + ip.getIp());
                    tempEnv.put(ip.getNetName(), ip.getIp());
                }
                log.debug("adding floatingIp: " + vnfcInstance.getFloatingIps());
                for (Ip fip : vnfcInstance.getFloatingIps()) {
                    tempEnv.put(fip.getNetName() + "_floatingIp", fip.getIp());
                }

                tempEnv.put("hostname", vnfcInstance.getHostname());
                //Add cause to the environment variables
                tempEnv.put("cause", cause);

                tempEnv = modifyUnsafeEnvVarNames(tempEnv);
                env.putAll(tempEnv);
                log.info("The Environment Variables for script " + script + " are: " + env);

                String command = getJsonObject("EXECUTE", script, env).toString();
                String output = executeActionOnEMS(vnfcInstance.getHostname(), command,
                        virtualNetworkFunctionRecord, vnfcInstance);
                res.add(output);
                saveLogToFile(virtualNetworkFunctionRecord, script, vnfcInstance, output);
                for (String key : tempEnv.keySet()) {
                    env.remove(key);
                }
            }
        }
        return res;
    }

    private Iterable<String> executeScriptsForEvent(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance vnfcInstance, Event event, VNFRecordDependency dependency) throws Exception {
        Map<String, String> env = getMap(virtualNetworkFunctionRecord);
        List<String> res = new ArrayList<>();
        LifecycleEvent le = VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), event);
        log.trace("The number of scripts for " + virtualNetworkFunctionRecord.getName() + " are: "
                + le.getLifecycle_events());
        log.debug("DEPENDENCY IS: " + dependency);
        if (le != null) {
            for (String script : le.getLifecycle_events()) {
                int indexOf = script.indexOf('_');
                VNFCDependencyParameters vnfcDependencyParameters = null;
                String type = null;
                if (indexOf != -1) {
                    type = script.substring(0, indexOf);
                    vnfcDependencyParameters = dependency.getVnfcParameters().get(type);
                }
                if (vnfcDependencyParameters != null) {
                    log.debug("There are " + vnfcDependencyParameters.getParameters().size()
                            + " VNFCInstanceForeign");
                    for (String vnfcForeignId : vnfcDependencyParameters.getParameters().keySet()) {
                        log.info("Running script: " + script + " for VNFCInstance foreign id " + vnfcForeignId);

                        log.info("Sending command: " + script + " to adding relation with type: " + type
                                + " from VirtualNetworkFunctionRecord " + virtualNetworkFunctionRecord.getName());

                        Map<String, String> tempEnv = new HashMap<>();

                        //Adding own ips
                        for (Ip ip : vnfcInstance.getIps()) {
                            log.debug("Adding net: " + ip.getNetName() + " with value: " + ip.getIp());
                            tempEnv.put(ip.getNetName(), ip.getIp());
                        }

                        //Adding own floating ip
                        log.debug("adding floatingIp: " + vnfcInstance.getFloatingIps());
                        for (Ip fip : vnfcInstance.getFloatingIps()) {
                            tempEnv.put(fip.getNetName() + "_floatingIp", fip.getIp());
                        }
                        //Adding foreign parameters such as ip
                        if (script.contains("_")) {
                            //Adding foreign parameters such as ip
                            Map<String, String> parameters = dependency.getParameters().get(type).getParameters();
                            for (Entry<String, String> param : parameters.entrySet()) {
                                tempEnv.put(type + "_" + param.getKey(), param.getValue());
                            }

                            Map<String, String> parametersVNFC = vnfcDependencyParameters.getParameters()
                                    .get(vnfcForeignId).getParameters();
                            for (Entry<String, String> param : parametersVNFC.entrySet()) {
                                tempEnv.put(type + "_" + param.getKey(), param.getValue());
                            }
                        }

                        tempEnv.put("hostname", vnfcInstance.getHostname());
                        tempEnv = modifyUnsafeEnvVarNames(tempEnv);
                        env.putAll(tempEnv);
                        log.info("The Environment Variables for script " + script + " are: " + env);

                        String command = getJsonObject("EXECUTE", script, env).toString();
                        String output = executeActionOnEMS(vnfcInstance.getHostname(), command,
                                virtualNetworkFunctionRecord, vnfcInstance);
                        res.add(output);

                        saveLogToFile(virtualNetworkFunctionRecord, script, vnfcInstance, output);
                        for (String key : tempEnv.keySet()) {
                            env.remove(key);
                        }
                    }
                }
            }
        }
        return res;
    }

    @Override
    public void checkInstantiationFeasibility() {
    }

    @Override
    public VirtualNetworkFunctionRecord heal(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance component, String cause) throws Exception {

        if ("switchToStandby".equals(cause)) {
            for (VirtualDeploymentUnit virtualDeploymentUnit : virtualNetworkFunctionRecord.getVdu()) {
                for (VNFCInstance vnfcInstance : virtualDeploymentUnit.getVnfc_instance()) {
                    if (vnfcInstance.getId().equals(component.getId())
                            && "standby".equalsIgnoreCase(vnfcInstance.getState())) {
                        log.debug("Activation of the standby component");
                        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(),
                                Event.START) != null) {
                            log.debug("Executed scripts for event START " + this
                                    .executeScriptsForEvent(virtualNetworkFunctionRecord, component, Event.START));
                        }
                        log.debug("Changing the status from standby to active");
                        //This is inside the vnfr
                        vnfcInstance.setState("ACTIVE");
                        // This is a copy of the object received as parameter and modified.
                        // It will be sent to the orchestrator
                        component.setState("ACTIVE");
                        break;
                    }
                }
            }
        } else if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(),
                Event.HEAL) != null) {
            if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.HEAL)
                    .getLifecycle_events() != null) {
                log.debug("Heal method started");
                log.info("-----------------------------------------------------------------------");
                String output = "\n--------------------\n--------------------\n";
                for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, component, Event.HEAL,
                        cause)) {
                    output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                            .replaceAll("\\\\n", "\n");
                    output += "\n--------------------\n";
                }
                output += "\n--------------------\n";
                log.info("Executed script for HEAL. Output was: \n\n" + output);
                log.info("-----------------------------------------------------------------------");
            }
        }
        return virtualNetworkFunctionRecord;
    }

    @Override
    public VirtualNetworkFunctionRecord updateSoftware(Script script,
            VirtualNetworkFunctionRecord virtualNetworkFunctionRecord) throws Exception {
        for (VirtualDeploymentUnit vdu : virtualNetworkFunctionRecord.getVdu()) {
            for (VNFCInstance vnfcInstance : vdu.getVnfc_instance()) {
                updateScript(script, virtualNetworkFunctionRecord, vnfcInstance);
            }
        }
        return virtualNetworkFunctionRecord;
    }

    private void updateScript(Script script, VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance vnfcInstance) throws Exception {
        JsonObject jsonMessage = getJsonObjectForScript("SCRIPTS_UPDATE",
                Base64.encodeBase64String(script.getPayload()), script.getName(), scriptPath);
        executeActionOnEMS(vnfcInstance.getHostname(), jsonMessage.toString(), virtualNetworkFunctionRecord,
                vnfcInstance);
    }

    @Override
    public void upgradeSoftware() {
    }

    @Override
    public VirtualNetworkFunctionRecord modify(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFRecordDependency dependency) throws Exception {
        log.trace("VirtualNetworkFunctionRecord VERSION is: " + virtualNetworkFunctionRecord.getHb_version());
        log.info("executing modify for VNFR: " + virtualNetworkFunctionRecord.getName());

        log.debug("Got dependency: " + dependency);
        log.debug("Parameters are: ");
        for (Entry<String, DependencyParameters> entry : dependency.getParameters().entrySet()) {
            log.debug("Source type: " + entry.getKey());
            log.debug("Parameters: " + entry.getValue().getParameters());
        }

        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(),
                Event.CONFIGURE) != null) {
            log.debug("LifeCycle events: " + VnfmUtils
                    .getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.CONFIGURE)
                    .getLifecycle_events());
            log.info("-----------------------------------------------------------------------");
            String output = "\n--------------------\n--------------------\n";
            for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, Event.CONFIGURE,
                    dependency)) {
                output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                        .replaceAll("\\\\n", "\n");
                output += "\n--------------------\n";
            }
            output += "\n--------------------\n";
            log.info("Executed script for CONFIGURE. Output was: \n\n" + output);
            log.info("-----------------------------------------------------------------------");
        } else {
            log.debug("No LifeCycle events for Event.CONFIGURE");
        }
        return virtualNetworkFunctionRecord;
    }

    //When the EMS reveive a script which terminate the vnf, the EMS is still running.
    //Once the vnf is terminated NFVO requests deletion of resources (MANO B.5) and the EMS will be terminated.
    @Override
    public VirtualNetworkFunctionRecord terminate(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord)
            throws Exception {
        log.debug("Termination of VNF: " + virtualNetworkFunctionRecord.getName());
        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(),
                Event.TERMINATE) != null) {
            String output = "\n--------------------\n--------------------\n";
            for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, Event.TERMINATE)) {
                output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                        .replaceAll("\\\\n", "\n");
                output += "\n--------------------\n";
            }
            output += "\n--------------------\n";
            log.info("Executed script for TERMINATE. Output was: \n\n" + output);
        }
        return virtualNetworkFunctionRecord;
    }

    @Override
    public void handleError(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord) {
        log.error("Received Error for VNFR " + virtualNetworkFunctionRecord.getName());
        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.ERROR) != null) {
            String output = "\n--------------------\n--------------------\n";
            try {
                for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, Event.ERROR)) {
                    output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                            .replaceAll("\\\\n", "\n");
                    output += "\n--------------------\n";
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("Exception executing Error handling");
            }
            output += "\n--------------------\n";
            log.info("Executed script for ERROR. Output was: \n\n" + output);
        }
    }

    @Override
    protected void fillSpecificProvides(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord) {
        for (ConfigurationParameter configurationParameter : virtualNetworkFunctionRecord.getProvides()
                .getConfigurationParameters()) {
            if (!configurationParameter.getConfKey().startsWith("#nfvo:")) {
                configurationParameter.setValue(String.valueOf((int) (Math.random() * 100)));
                log.debug("Setting: " + configurationParameter.getConfKey() + " with value: "
                        + configurationParameter.getValue());
            }
        }
    }

    @Override
    public VirtualNetworkFunctionRecord start(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord)
            throws Exception {

        log.info("Starting vnfr: " + virtualNetworkFunctionRecord.getName());

        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.START) != null) {
            if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.START)
                    .getLifecycle_events() != null) {
                String output = "\n--------------------\n--------------------\n";
                for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, Event.START)) {
                    output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                            .replaceAll("\\\\n", "\n");
                    output += "\n--------------------\n";
                }
                output += "\n--------------------\n";
                log.info("Executed script for START. Output was: \n\n" + output);
            }
        }
        return virtualNetworkFunctionRecord;
    }

    @Override
    public VirtualNetworkFunctionRecord stop(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord)
            throws Exception {

        log.info("Stopping vnfr: " + virtualNetworkFunctionRecord.getName());

        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.STOP) != null) {
            if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.STOP)
                    .getLifecycle_events() != null) {
                String output = "\n--------------------\n--------------------\n";
                for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, Event.STOP)) {
                    output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                            .replaceAll("\\\\n", "\n");
                    output += "\n--------------------\n";
                }
                output += "\n--------------------\n";
                log.info("Executed script for STOP. Output was: \n\n" + output);
            }
        }
        return virtualNetworkFunctionRecord;
    }

    @Override
    public VirtualNetworkFunctionRecord startVNFCInstance(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance vnfcInstance) throws Exception {

        log.info("Starting vnfc instance: " + vnfcInstance.getHostname());

        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.START) != null) {
            if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.START)
                    .getLifecycle_events() != null) {
                String output = "\n--------------------\n--------------------\n";
                for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, vnfcInstance,
                        Event.START)) {
                    output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                            .replaceAll("\\\\n", "\n");
                    output += "\n--------------------\n";
                }
                output += "\n--------------------\n";
                log.info("Executed script for START on VNFC Instance " + vnfcInstance.getHostname()
                        + ". Output was: \n\n" + output);
            }
        }

        return virtualNetworkFunctionRecord;
    }

    @Override
    public VirtualNetworkFunctionRecord stopVNFCInstance(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance vnfcInstance) throws Exception {

        log.info("Stopping vnfc instance: " + vnfcInstance.getHostname());

        if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.STOP) != null) {
            if (VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), Event.STOP)
                    .getLifecycle_events() != null) {
                String output = "\n--------------------\n--------------------\n";
                for (String result : executeScriptsForEvent(virtualNetworkFunctionRecord, vnfcInstance,
                        Event.STOP)) {
                    output += this.parser.fromJson(result, JsonObject.class).get("output").getAsString()
                            .replaceAll("\\\\n", "\n");
                    output += "\n--------------------\n";
                }
                output += "\n--------------------\n";
                log.info("Executed script for STOP on VNFC Instance " + vnfcInstance.getHostname()
                        + ". Output was: \n\n" + output);
            }
        }

        return virtualNetworkFunctionRecord;
    }

    @Override
    public VirtualNetworkFunctionRecord configure(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord)
            throws Exception {
        return virtualNetworkFunctionRecord;
    }

    @Override
    public VirtualNetworkFunctionRecord resume(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            VNFCInstance vnfcInstance, VNFRecordDependency dependency) throws Exception {
        return virtualNetworkFunctionRecord;
    }

    @Override
    public void NotifyChange() {
    }

    @Override
    protected void checkEMS(String hostname) {
        int i = 0;
        while (true) {
            log.debug("Waiting for " + hostname + " ems to be started... (" + i * 5 + " secs)");
            i++;
            try {
                checkEmsStarted(hostname);
                break;
            } catch (RuntimeException e) {
                if (i == this.waitForEms / 5) {
                    throw e;
                }
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    @Override
    protected void checkEmsStarted(String hostname) {
        if (!this.emsRegistrator.getHostnames().contains(hostname.toLowerCase())) {
            throw new RuntimeException("no ems for hostame: " + hostname);
        }
        this.emsRegistrator.unregister(hostname.toLowerCase());
    }

    private String executeActionOnEMS(String vduHostname, String command, VirtualNetworkFunctionRecord vnfr,
            VNFCInstance vnfcInstance) throws Exception {
        log.trace("Sending message and waiting: " + command + " to " + vduHostname);
        log.info("Waiting answer from EMS - " + vduHostname);

        String response = this.vnfmHelper.sendAndReceive(command, "vnfm." + vduHostname.toLowerCase() + ".actions");

        log.debug("Received from EMS (" + vduHostname + "): " + response);

        if (response == null) {
            throw new NullPointerException("Response from EMS is null");
        }

        JsonObject jsonObject = this.parser.fromJson(response, JsonObject.class);

        if (jsonObject.get("status").getAsInt() == 0) {
            try {
                log.debug("Output from EMS (" + vduHostname + ") is: " + jsonObject.get("output"));
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            }
        } else {
            String err = jsonObject.get("err").getAsString();
            log.error(err);
            vnfcInstance.setState("error");
            saveLogToFile(vnfr, parser.fromJson(command, JsonObject.class).get("payload").getAsString(),
                    vnfcInstance, response, true);
            throw new VnfmSdkException("EMS (" + vduHostname + ") had the following error: " + err);
        }
        return response;
    }

    public Iterable<String> executeScriptsForEvent(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            Event event) throws Exception { //TODO make it parallel
        Map<String, String> env = getMap(virtualNetworkFunctionRecord);
        Collection<String> res = new ArrayList<>();
        LifecycleEvent le = VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), event);

        if (le != null) {
            log.trace("The number of scripts for " + virtualNetworkFunctionRecord.getName() + " are: "
                    + le.getLifecycle_events());
            for (String script : le.getLifecycle_events()) {
                log.info("Sending script: " + script + " to VirtualNetworkFunctionRecord: "
                        + virtualNetworkFunctionRecord.getName());
                for (VirtualDeploymentUnit vdu : virtualNetworkFunctionRecord.getVdu()) {
                    for (VNFCInstance vnfcInstance : vdu.getVnfc_instance()) {

                        Map<String, String> tempEnv = new HashMap<>();
                        for (Ip ip : vnfcInstance.getIps()) {
                            log.debug("Adding net: " + ip.getNetName() + " with value: " + ip.getIp());
                            tempEnv.put(ip.getNetName(), ip.getIp());
                        }
                        log.debug("adding floatingIp: " + vnfcInstance.getFloatingIps());
                        for (Ip fip : vnfcInstance.getFloatingIps()) {
                            tempEnv.put(fip.getNetName() + "_floatingIp", fip.getIp());
                        }

                        tempEnv.put("hostname", vnfcInstance.getHostname());
                        tempEnv = modifyUnsafeEnvVarNames(tempEnv);
                        env.putAll(tempEnv);
                        log.info("Environment Variables are: " + env);

                        String command = getJsonObject("EXECUTE", script, env).toString();
                        String output = executeActionOnEMS(vnfcInstance.getHostname(), command,
                                virtualNetworkFunctionRecord, vnfcInstance);
                        res.add(output);

                        saveLogToFile(virtualNetworkFunctionRecord, script, vnfcInstance, output);
                        for (String key : tempEnv.keySet()) {
                            env.remove(key);
                        }
                    }
                }
            }
        }
        return res;
    }

    public Iterable<String> executeScriptsForEvent(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord,
            Event event, VNFRecordDependency dependency) throws Exception {
        Map<String, String> env = getMap(virtualNetworkFunctionRecord);
        LifecycleEvent le = VnfmUtils.getLifecycleEvent(virtualNetworkFunctionRecord.getLifecycle_event(), event);
        List<String> res = new ArrayList<>();
        if (le != null) {
            for (String script : le.getLifecycle_events()) {

                String type = null;
                if (script.contains("_")) {
                    type = script.substring(0, script.indexOf('_'));
                    log.info("Sending command: " + script + " to adding relation with type: " + type
                            + " from VirtualNetworkFunctionRecord " + virtualNetworkFunctionRecord.getName());
                }

                for (VirtualDeploymentUnit vdu : virtualNetworkFunctionRecord.getVdu()) {
                    for (VNFCInstance vnfcInstance : vdu.getVnfc_instance()) {
                        if (dependency.getVnfcParameters().get(type) != null) {
                            for (String vnfcId : dependency.getVnfcParameters().get(type).getParameters()
                                    .keySet()) {

                                Map<String, String> tempEnv = new HashMap<>();

                                //Adding own ips
                                for (Ip ip : vnfcInstance.getIps()) {
                                    log.debug("Adding net: " + ip.getNetName() + " with value: " + ip.getIp());
                                    tempEnv.put(ip.getNetName(), ip.getIp());
                                }

                                //Adding own floating ip
                                for (Ip fip : vnfcInstance.getFloatingIps()) {
                                    log.debug("adding floatingIp: " + fip.getNetName() + " = " + fip.getIp());
                                    tempEnv.put(fip.getNetName() + "_floatingIp", fip.getIp());
                                }

                                if (script.contains("_")) {
                                    //Adding foreign parameters such as ip
                                    log.debug("Fetching parameter from dependency of type: " + type);
                                    Map<String, String> parameters = dependency.getParameters().get(type)
                                            .getParameters();

                                    for (Map.Entry<String, String> param : parameters.entrySet()) {
                                        log.debug("adding param: " + type + "_" + param.getKey() + " = "
                                                + param.getValue());
                                        tempEnv.put(type + "_" + param.getKey(), param.getValue());
                                    }

                                    Map<String, String> parametersVNFC = dependency.getVnfcParameters().get(type)
                                            .getParameters().get(vnfcId).getParameters();
                                    for (Map.Entry<String, String> param : parametersVNFC.entrySet()) {
                                        log.debug("adding param: " + type + "_" + param.getKey() + " = "
                                                + param.getValue());
                                        tempEnv.put(type + "_" + param.getKey(), param.getValue());
                                    }
                                }

                                tempEnv.put("hostname", vnfcInstance.getHostname());
                                tempEnv = modifyUnsafeEnvVarNames(tempEnv);
                                env.putAll(tempEnv);
                                log.info("Environment Variables are: " + env);

                                String command = getJsonObject("EXECUTE", script, env).toString();
                                String output = executeActionOnEMS(vnfcInstance.getHostname(), command,
                                        virtualNetworkFunctionRecord, vnfcInstance);
                                res.add(output);

                                saveLogToFile(virtualNetworkFunctionRecord, script, vnfcInstance, output);
                                for (String key : tempEnv.keySet()) {
                                    env.remove(key);
                                }
                            }
                        }
                    }
                }
            }
        }
        return res;
    }

    public void saveScriptOnEms(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord, Object scripts)
            throws Exception {

        log.debug("Scripts are: " + scripts.getClass().getName());

        if (scripts instanceof String) {
            String scriptLink = (String) scripts;
            log.debug("Scripts are: " + scriptLink);
            JsonObject jsonMessage = getJsonObject("CLONE_SCRIPTS", scriptLink, this.scriptPath);

            for (VirtualDeploymentUnit virtualDeploymentUnit : virtualNetworkFunctionRecord.getVdu()) {
                for (VNFCInstance vnfcInstance : virtualDeploymentUnit.getVnfc_instance()) {
                    executeActionOnEMS(vnfcInstance.getHostname(), jsonMessage.toString(),
                            virtualNetworkFunctionRecord, vnfcInstance);
                }
            }
        } else if (scripts instanceof Set) {
            Iterable<Script> scriptSet = (Set<Script>) scripts;

            for (Script script : scriptSet) {
                log.debug("Sending script encoded base64 ");
                String base64String = Base64.encodeBase64String(script.getPayload());
                log.trace("The base64 string is: " + base64String);
                JsonObject jsonMessage = getJsonObjectForScript("SAVE_SCRIPTS", base64String, script.getName(),
                        this.scriptPath);
                for (VirtualDeploymentUnit virtualDeploymentUnit : virtualNetworkFunctionRecord.getVdu()) {
                    for (VNFCInstance vnfcInstance : virtualDeploymentUnit.getVnfc_instance()) {
                        executeActionOnEMS(vnfcInstance.getHostname(), jsonMessage.toString(),
                                virtualNetworkFunctionRecord, vnfcInstance);
                    }
                }
            }
        }
    }

    public void saveScriptOnEms(VNFCInstance vnfcInstance, Object scripts,
            VirtualNetworkFunctionRecord virtualNetworkFunctionRecord) throws Exception {

        log.debug("Scripts are: " + scripts.getClass().getName());

        if (scripts instanceof String) {
            String scriptLink = (String) scripts;
            log.debug("Scripts are: " + scriptLink);
            JsonObject jsonMessage = getJsonObject("CLONE_SCRIPTS", scriptLink, this.scriptPath);
            executeActionOnEMS(vnfcInstance.getHostname(), jsonMessage.toString(), virtualNetworkFunctionRecord,
                    vnfcInstance);
        } else if (scripts instanceof Set) {
            Iterable<Script> scriptSet = (Set<Script>) scripts;
            for (Script script : scriptSet) {
                log.debug("Sending script encoded base64 ");
                String base64String = Base64.encodeBase64String(script.getPayload());
                log.trace("The base64 string is: " + base64String);
                JsonObject jsonMessage = getJsonObjectForScript("SAVE_SCRIPTS", base64String, script.getName(),
                        this.scriptPath);
                executeActionOnEMS(vnfcInstance.getHostname(), jsonMessage.toString(), virtualNetworkFunctionRecord,
                        vnfcInstance);
            }
        }
    }

    private JsonObject getJsonObject(String action, String payload, String scriptPath) {
        JsonObject jsonMessage = new JsonObject();
        jsonMessage.addProperty("action", action);
        jsonMessage.addProperty("payload", payload);
        jsonMessage.addProperty("script-path", scriptPath);
        return jsonMessage;
    }

    private JsonObject getJsonObject(String action, String payload, Map<String, String> env) {
        JsonObject jsonMessage = new JsonObject();
        jsonMessage.addProperty("action", action);
        jsonMessage.addProperty("payload", payload);
        jsonMessage.add("env", this.parser.fromJson(this.parser.toJson(env), JsonObject.class));
        return jsonMessage;
    }

    private JsonObject getJsonObjectForScript(String save_scripts, String payload, String name, String scriptPath) {
        JsonObject jsonMessage = new JsonObject();
        jsonMessage.addProperty("action", save_scripts);
        jsonMessage.addProperty("payload", payload);
        jsonMessage.addProperty("name", name);
        jsonMessage.addProperty("script-path", scriptPath);
        return jsonMessage;
    }

    private Map<String, String> getMap(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord) {
        Map<String, String> res = new HashMap<>();
        for (ConfigurationParameter configurationParameter : virtualNetworkFunctionRecord.getProvides()
                .getConfigurationParameters()) {
            res.put(configurationParameter.getConfKey(), configurationParameter.getValue());
        }
        for (ConfigurationParameter configurationParameter : virtualNetworkFunctionRecord.getConfigurations()
                .getConfigurationParameters()) {
            res.put(configurationParameter.getConfKey(), configurationParameter.getValue());
        }
        res = modifyUnsafeEnvVarNames(res);
        return res;
    }

    @Override
    protected void setup() {
        super.setup();
        scriptPath = properties.getProperty("script-path", "/opt/openbaton/scripts");
        if (this.old > 0) {
            File f = new File(this.scriptsLogPath);
            f.mkdirs();
        }
    }

    @Override
    protected String getUserData() {
        String result = convertStreamToString(AbstractVnfm.class.getResourceAsStream("/user-data.sh"));

        log.debug(emsVersion);

        result = result.replace("export MONITORING_IP=", "export MONITORING_IP=" + monitoringIp);
        result = result.replace("export TIMEZONE=", "export TIMEZONE=" + timezone);
        result = result.replace("export BROKER_IP=", "export BROKER_IP=" + brokerIp);
        result = result.replace("export BROKER_PORT=", "export BROKER_PORT=" + brokerPort);
        result = result.replace("export USERNAME=", "export USERNAME=" + username);
        result = result.replace("export PASSWORD=", "export PASSWORD=" + password);
        result = result.replace("export EXCHANGE_NAME=", "export EXCHANGE_NAME=" + exchangeName);
        result = result.replace("export EMS_HEARTBEAT=", "export EMS_HEARTBEAT=" + emsHeartbeat);
        result = result.replace("export EMS_AUTODELETE=", "export EMS_AUTODELETE=" + emsAutodelete);
        result = result.replace("export EMS_VERSION=", "export EMS_VERSION=" + emsVersion);
        result = result.replace("export ENDPOINT=", "export ENDPOINT=" + type);

        return result;
    }
}