CharafeddineMechalikh/PureEdgeSim

View on GitHub
PureEdgeSim/com/mechalikh/pureedgesim/datacentersmanager/DefaultComputingNodesGenerator.java

Summary

Maintainability
C
1 day
Test Coverage
/**
 *     PureEdgeSim:  A Simulation Framework for Performance Evaluation of Cloud, Edge and Mist Computing Environments 
 *
 *     This file is part of PureEdgeSim Project.
 *
 *     PureEdgeSim is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     PureEdgeSim is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with PureEdgeSim. If not, see <http://www.gnu.org/licenses/>.
 *     
 *     @author Charafeddine Mechalikh
 **/
package com.mechalikh.pureedgesim.datacentersmanager;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; 
import java.util.Random;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.mechalikh.pureedgesim.energy.EnergyModelComputingNode;
import com.mechalikh.pureedgesim.locationmanager.Location;
import com.mechalikh.pureedgesim.locationmanager.MobilityModel;
import com.mechalikh.pureedgesim.scenariomanager.SimulationParameters;
import com.mechalikh.pureedgesim.scenariomanager.SimulationParameters.TYPES;
import com.mechalikh.pureedgesim.simulationmanager.SimulationManager;

public class DefaultComputingNodesGenerator extends ComputingNodesGenerator {

    public DefaultComputingNodesGenerator(SimulationManager simulationManager,
            Class<? extends MobilityModel> mobilityModelClass, Class<? extends ComputingNode> computingNodeClass) {
        super(simulationManager, mobilityModelClass, computingNodeClass);
    }
    
    @Override
    public void generateDatacentersAndDevices() {

        // Generate Edge and Cloud data centers.
        generateDataCenters(SimulationParameters.cloudDataCentersFile, SimulationParameters.TYPES.CLOUD); 

        generateDataCenters(SimulationParameters.edgeDataCentersFile, SimulationParameters.TYPES.EDGE_DATACENTER); 

        // Generate edge devices.
        generateEdgeDevices();

        getSimulationManager().getSimulationLogger()
                .print("%s - Datacenters and devices were generated", getClass().getSimpleName());

    }

    /**
     * Generates edge devices
     */
    public void generateEdgeDevices() {
        // Generate edge devices instances from edge devices types in xml file.
        try (InputStream devicesFile = new FileInputStream(SimulationParameters.edgeDevicesFile)) {

            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

            // Disable access to external entities in XML parsing, by disallowing DocType
            // declaration
            dbFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(devicesFile);
            NodeList nodeList = doc.getElementsByTagName("device");
            Element edgeElement = null;

            // Load all devices types in edge_devices.xml file.
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node edgeNode = nodeList.item(i);
                edgeElement = (Element) edgeNode;
                generateDevicesInstances(edgeElement);
            }

            // if percentage of generated devices is < 100%.
            if (mistOnlyList.size() < getSimulationManager().getScenario().getDevicesCount())
                getSimulationManager().getSimulationLogger().print("%s - Wrong percentages values (the sum is inferior than 100%), check edge_devices.xml file !", getClass().getSimpleName());
            // Add more devices.
            if (edgeElement != null) {
                int missingInstances = getSimulationManager().getScenario().getDevicesCount() - mistOnlyList.size();
                for (int k = 0; k < missingInstances; k++) {
                    ComputingNode newDevice = createComputingNode(edgeElement, SimulationParameters.TYPES.EDGE_DEVICE);
                    insertEdgeDevice(newDevice);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * Puts the newly generated edge device in corresponding lists.
     */
    protected void insertEdgeDevice(ComputingNode newDevice) {
        mistOnlyList.add(newDevice);
        allNodesList.add(newDevice);
        if (!newDevice.isSensor()) {
            mistOnlyListSensorsExcluded.add(newDevice);
            mistAndCloudListSensorsExcluded.add(newDevice);
            mistAndEdgeListSensorsExcluded.add(newDevice);
            allNodesListSensorsExcluded.add(newDevice);
        }
    }
    
    /**
     * Generates the required number of instances for each type of edge devices.
     * 
     * @param type The type of edge devices.
     */
    protected void generateDevicesInstances(Element type) {

        int instancesPercentage = Integer.parseInt(type.getElementsByTagName("percentage").item(0).getTextContent());

        // Find the number of instances of this type of devices
        int devicesInstances = getSimulationManager().getScenario().getDevicesCount() * instancesPercentage / 100;

        for (int j = 0; j < devicesInstances; j++) {
            if (mistOnlyList.size() > getSimulationManager().getScenario().getDevicesCount()) {
                getSimulationManager().getSimulationLogger().print("%s - Wrong percentages values (the sum is superior than 100%), check edge_devices.xml file !",getClass().getSimpleName());
                break;
            }

            try {
                insertEdgeDevice(createComputingNode(type, SimulationParameters.TYPES.EDGE_DEVICE));
            } catch (NoSuchAlgorithmException | NoSuchMethodException | SecurityException | InstantiationException
                    | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                e.printStackTrace();
            }

        }
    }
    
    /**
     * Generates the Cloud and Edge data centers.
     * 
     * @param file The configuration file.
     * @param type The type, whether a CLOUD data center or an EDGE one.
     */
    protected void generateDataCenters(String file, TYPES type) {
        // Fill list with edge data centers
        try (InputStream serversFile = new FileInputStream(file)) {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

            // Disable access to external entities in XML parsing, by disallowing DocType
            // declaration
            dbFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(serversFile);
            NodeList datacenterList = doc.getElementsByTagName("datacenter");
            for (int i = 0; i < datacenterList.getLength(); i++) {
                Element datacenterElement = (Element) datacenterList.item(i);
                ComputingNode computingNode = createComputingNode(datacenterElement, type);
                if (computingNode.getType() == TYPES.CLOUD) {
                    cloudOnlyList.add(computingNode);
                    mistAndCloudListSensorsExcluded.add(computingNode);
                    if (SimulationParameters.enableOrchestrators
                            && "CLOUD".equals(SimulationParameters.deployOrchestrators)) {
                        orchestratorsList.add(computingNode);
                    }
                } else {
                    edgeOnlyList.add(computingNode);
                    mistAndEdgeListSensorsExcluded.add(computingNode);
                    if (SimulationParameters.enableOrchestrators
                            && "EDGE".equals(SimulationParameters.deployOrchestrators)) {
                        orchestratorsList.add(computingNode);
                    }
                }
                allNodesList.add(computingNode);
                allNodesListSensorsExcluded.add(computingNode);
                edgeAndCloudList.add(computingNode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    
    /**
     * Creates the computing nodes.
     * 
     * @see #generateDataCenters(String, TYPES)
     * @see #generateDevicesInstances(Element)
     * 
     * @param datacenterElement The configuration file.
     * @param type              The type, whether an MIST (edge) device, an EDGE
     *                          data center, or a CLOUD one.
     * @throws NoSuchAlgorithmException
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    protected ComputingNode createComputingNode(Element datacenterElement, SimulationParameters.TYPES type)
            throws NoSuchAlgorithmException, NoSuchMethodException, SecurityException, InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        // SecureRandom is preferred to generate random values.
        Random random = SecureRandom.getInstanceStrong();
        Boolean mobile = false;
        double speed = 0;
        double minPauseDuration = 0;
        double maxPauseDuration = 0;
        double minMobilityDuration = 0;
        double maxMobilityDuration = 0;
        int xPosition = -1;
        int yPosition = -1;
        double idleConsumption = Double
                .parseDouble(datacenterElement.getElementsByTagName("idleConsumption").item(0).getTextContent());
        double maxConsumption = Double
                .parseDouble(datacenterElement.getElementsByTagName("maxConsumption").item(0).getTextContent());
        Location datacenterLocation = new Location(xPosition, yPosition);
        int numOfCores = Integer.parseInt(datacenterElement.getElementsByTagName("cores").item(0).getTextContent());
        double mips = Double.parseDouble(datacenterElement.getElementsByTagName("mips").item(0).getTextContent());
        double storage = Double.parseDouble(datacenterElement.getElementsByTagName("storage").item(0).getTextContent());
        double ram = Double.parseDouble(datacenterElement.getElementsByTagName("ram").item(0).getTextContent());

        Constructor<?> datacenterConstructor = computingNodeClass.getConstructor(SimulationManager.class, double.class,
                int.class, double.class, double.class);
        ComputingNode computingNode = (ComputingNode) datacenterConstructor.newInstance(getSimulationManager(), mips,
                numOfCores, storage, ram);

        computingNode.setAsOrchestrator(Boolean
                .parseBoolean(datacenterElement.getElementsByTagName("isOrchestrator").item(0).getTextContent()));

        if (computingNode.isOrchestrator())
            orchestratorsList.add(computingNode);

        computingNode.setEnergyModel(new EnergyModelComputingNode(maxConsumption, idleConsumption));

        if (type == SimulationParameters.TYPES.EDGE_DATACENTER) {
            String name = datacenterElement.getAttribute("name");
            computingNode.setName(name);
            Element location = (Element) datacenterElement.getElementsByTagName("location").item(0);
            xPosition = Integer.parseInt(location.getElementsByTagName("x_pos").item(0).getTextContent());
            yPosition = Integer.parseInt(location.getElementsByTagName("y_pos").item(0).getTextContent());
            datacenterLocation = new Location(xPosition, yPosition);

            for (int i = 0; i < edgeOnlyList.size(); i++)
                if (datacenterLocation.equals(edgeOnlyList.get(i).getMobilityModel().getCurrentLocation()))
                    throw new IllegalArgumentException(
                            " Each Edge Data Center must have a different location, check the \"edge_datacenters.xml\" file!");

            computingNode.setPeriphery(
                    Boolean.parseBoolean(datacenterElement.getElementsByTagName("periphery").item(0).getTextContent()));

        } else if (type == SimulationParameters.TYPES.EDGE_DEVICE) {
            mobile = Boolean.parseBoolean(datacenterElement.getElementsByTagName("mobility").item(0).getTextContent());
            speed = Double.parseDouble(datacenterElement.getElementsByTagName("speed").item(0).getTextContent());
            minPauseDuration = Double
                    .parseDouble(datacenterElement.getElementsByTagName("minPauseDuration").item(0).getTextContent());
            maxPauseDuration = Double
                    .parseDouble(datacenterElement.getElementsByTagName("maxPauseDuration").item(0).getTextContent());
            minMobilityDuration = Double.parseDouble(
                    datacenterElement.getElementsByTagName("minMobilityDuration").item(0).getTextContent());
            maxMobilityDuration = Double.parseDouble(
                    datacenterElement.getElementsByTagName("maxMobilityDuration").item(0).getTextContent());
            computingNode.getEnergyModel().setBattery(
                    Boolean.parseBoolean(datacenterElement.getElementsByTagName("battery").item(0).getTextContent()));
            computingNode.getEnergyModel().setBatteryCapacity(Double
                    .parseDouble(datacenterElement.getElementsByTagName("batteryCapacity").item(0).getTextContent()));
            computingNode.getEnergyModel().setIntialBatteryPercentage(Double.parseDouble(
                    datacenterElement.getElementsByTagName("initialBatteryLevel").item(0).getTextContent()));
            computingNode.getEnergyModel().setConnectivityType(
                    datacenterElement.getElementsByTagName("connectivity").item(0).getTextContent());
            computingNode.enableTaskGeneration(Boolean
                    .parseBoolean(datacenterElement.getElementsByTagName("generateTasks").item(0).getTextContent()));
            // Generate random location for edge devices
            datacenterLocation = new Location(random.nextInt(SimulationParameters.simulationMapWidth),
                    random.nextInt(SimulationParameters.simulationMapLength));
            getSimulationManager().getSimulationLogger()
                    .deepLog("DefaultComputingNodesGenerator- Edge device:" + mistOnlyList.size() + "    location: ( "
                            + datacenterLocation.getXPos() + "," + datacenterLocation.getYPos() + " )");
        }
        computingNode.setType(type);
        Constructor<?> mobilityConstructor = mobilityModelClass.getConstructor(SimulationManager.class, Location.class);
        MobilityModel mobilityModel = ((MobilityModel) mobilityConstructor.newInstance(simulationManager,
                datacenterLocation)).setMobile(mobile).setSpeed(speed).setMinPauseDuration(minPauseDuration)
                .setMaxPauseDuration(maxPauseDuration).setMinMobilityDuration(minMobilityDuration)
                .setMaxMobilityDuration(maxMobilityDuration);

        computingNode.setMobilityModel(mobilityModel);

        return computingNode;
    }

}