Skip to content

Commit

Permalink
- Includes PlanetLabExample1
Browse files Browse the repository at this point in the history
- Updates UtilizationModelPlanetLab docs and performs small refactoring

Signed-off-by: Manoel Campos <manoelcampos@gmail.com>
  • Loading branch information
manoelcampos committed Aug 28, 2018
1 parent bdc0a59 commit fcf3796
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 29 deletions.
@@ -0,0 +1,188 @@
/*
* CloudSim Plus: A modern, highly-extensible and easier-to-use Framework for
* Modeling and Simulation of Cloud Computing Infrastructures and Services.
* http://cloudsimplus.org
*
* Copyright (C) 2015-2018 Universidade da Beira Interior (UBI, Portugal) and
* the Instituto Federal de Educa莽茫o Ci锚ncia e Tecnologia do Tocantins (IFTO, Brazil).
*
* This file is part of CloudSim Plus.
*
* CloudSim Plus 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.
*
* CloudSim Plus 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 CloudSim Plus. If not, see <http://www.gnu.org/licenses/>.
*/
package org.cloudsimplus.examples;

import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicySimple;
import org.cloudbus.cloudsim.brokers.DatacenterBroker;
import org.cloudbus.cloudsim.brokers.DatacenterBrokerSimple;
import org.cloudbus.cloudsim.cloudlets.Cloudlet;
import org.cloudbus.cloudsim.cloudlets.CloudletSimple;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.datacenters.Datacenter;
import org.cloudbus.cloudsim.datacenters.DatacenterSimple;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.hosts.HostSimple;
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple;
import org.cloudbus.cloudsim.resources.Pe;
import org.cloudbus.cloudsim.resources.PeSimple;
import org.cloudbus.cloudsim.schedulers.cloudlet.CloudletSchedulerTimeShared;
import org.cloudbus.cloudsim.schedulers.vm.VmSchedulerTimeShared;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelDynamic;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelPlanetLab;
import org.cloudbus.cloudsim.vms.Vm;
import org.cloudbus.cloudsim.vms.VmSimple;
import org.cloudsimplus.builders.tables.CloudletsTableBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

/**
* An example showing how to use the {@link UtilizationModelPlanetLab} class
* to define Cloudlets' CPU utilization based on <a href="https://www.planet-lab.org">PlanetLab's</a> trace files.
* Check the {@link #createCloudlets()} method.
*
* @author Manoel Campos da Silva Filho
* @since CloudSim Plus 4.0.0
*/
public class PlanetLabExample1 {
private static final int HOSTS = 3;
private static final int HOST_PES = 10;

private static final int VMS = 4;
private static final int VM_PES = 4;
private static final int VM_MIPS = 1000;

private static final int CLOUDLETS = 4;
private static final int CLOUDLET_PES = 2;
private static final int CLOUDLET_LENGTH = 100000000;

private static final String TRACE_FILE = "workload/planetlab/20110303/75-130-96-12_static_oxfr_ma_charter_com_irisaple_wup";

/**
* The time interval in which precise values can be got from
* the PlanetLab {@link #TRACE_FILE}.
* Such a value must be also defined as the Datacenter
* scheduling interval to ensure that Cloudlets' processing
* is updated with the values read from the trace file
* at the given interval.
*
* @see UtilizationModelPlanetLab#getSchedulingInterval()
*/
private static final int SCHEDULING_INTERVAL = 300;

private final CloudSim simulation;
private DatacenterBroker broker0;
private List<Vm> vmList;
private List<Cloudlet> cloudletList;
private Datacenter datacenter0;

public static void main(String[] args) {
new PlanetLabExample1();
}

public PlanetLabExample1() {
/*Enables just some level of log messages.
Make sure to import org.cloudsimplus.util.Log;*/
//Log.setLevel(ch.qos.logback.classic.Level.WARN);

simulation = new CloudSim();
datacenter0 = createDatacenter();

//Creates a broker that is a software acting on behalf a cloud customer to manage his/her VMs and Cloudlets
broker0 = new DatacenterBrokerSimple(simulation);

vmList = createVms();
cloudletList = createCloudlets();
broker0.submitVmList(vmList);
broker0.submitCloudletList(cloudletList);

simulation.start();

final List<Cloudlet> finishedCloudlets = broker0.getCloudletFinishedList();
new CloudletsTableBuilder(finishedCloudlets).build();
}

/**
* Creates a Datacenter and its Hosts.
*/
private Datacenter createDatacenter() {
final List<Host> hostList = new ArrayList<>(HOSTS);
for(int i = 0; i < HOSTS; i++) {
Host host = createHost();
hostList.add(host);
}

final DatacenterSimple dc = new DatacenterSimple(simulation, hostList, new VmAllocationPolicySimple());
dc.setSchedulingInterval(SCHEDULING_INTERVAL);
return dc;
}

private Host createHost() {
final List<Pe> peList = new ArrayList<>(HOST_PES);
//List of Host's CPUs (Processing Elements, PEs)
IntStream.range(0, HOST_PES).forEach(i -> peList.add(new PeSimple(1000, new PeProvisionerSimple())));

final long ram = 2048; //in Megabytes
final long bw = 10000; //in Megabits/s
final long storage = 1000000; //in Megabytes
Host host = new HostSimple(ram, bw, storage, peList);
host
.setRamProvisioner(new ResourceProvisionerSimple())
.setBwProvisioner(new ResourceProvisionerSimple())
.setVmScheduler(new VmSchedulerTimeShared());
return host;
}

/**
* Creates a list of VMs.
*/
private List<Vm> createVms() {
final List<Vm> list = new ArrayList<>(VMS);
for (int i = 0; i < VMS; i++) {
Vm vm =
new VmSimple(i, VM_MIPS, VM_PES)
.setRam(512).setBw(1000).setSize(10000)
.setCloudletScheduler(new CloudletSchedulerTimeShared());

list.add(vm);
}

return list;
}

/**
* Creates a list of Cloudlets setting their CPU UtilizationModel as
* a {@link UtilizationModelPlanetLab} that read CPU utilization from
* a PlanetLab trace file.
*/
private List<Cloudlet> createCloudlets() {
final List<Cloudlet> list = new ArrayList<>(CLOUDLETS);
final UtilizationModel utilizationCpu = UtilizationModelPlanetLab.getInstance(TRACE_FILE, SCHEDULING_INTERVAL);
for (int i = 0; i < CLOUDLETS; i++) {
Cloudlet cloudlet =
new CloudletSimple(i, CLOUDLET_LENGTH, CLOUDLET_PES)
.setFileSize(1024)
.setOutputSize(1024)
.setUtilizationModelCpu(utilizationCpu)
.setUtilizationModelBw(new UtilizationModelDynamic(0.2))
.setUtilizationModelRam(new UtilizationModelDynamic(0.4));
list.add(cloudlet);
}

return list;
}
}
Expand Up @@ -2,15 +2,34 @@

import org.cloudbus.cloudsim.util.ResourceLoader;

import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.util.Objects;

/**
* Defines the resource utilization model based on a
* Defines a resource utilization model based on a
* <a href="https://www.planet-lab.org">PlanetLab</a>
* Datacenter workload (trace) file.
*
* <p>
* Each PlanetLab trace file available contains CPU utilization measured at every 5 minutes (300 seconds) inside PlanetLab VMs.
* This value in seconds is commonly used for the {@link #getSchedulingInterval() scheduling interval} attribute
* when instantiating an object of this class.
* </p>
*/
public class UtilizationModelPlanetLab extends UtilizationModelAbstract {

/**
* The number of 5 minutes intervals inside one day (24 hours),
* since the available PlanetLab traces store resource utilization collected every
* 5 minutes along 24 hours.
* This is default number of samples to try to read from the trace file
* if a different value isn't provided to the constructors.
*/
private static final int DATA_SAMPLES = 289;

/**
* @see #getSchedulingInterval()
*/
Expand All @@ -25,20 +44,12 @@ public class UtilizationModelPlanetLab extends UtilizationModelAbstract {
*/
private final double[] utilization;

/**
* The number of 5 minutes intervals inside one day (24 hours),
* since the available PlanetLab traces store resource utilization collected every
* 5 minutes along 24 hours.
* This is default number of samples to try to read from the trace file.
*/
private static final int DATA_SAMPLES = 289;

/**
* Instantiates a new PlanetLab resource utilization model from a trace
* file inside the <b>application's resource directory</b>.
*
* @param traceFilePath The <b>relative path</b> of a PlanetLab Datacenter trace file.
* @param schedulingInterval the scheduling interval that defines the time interval in which precise utilization is be got
* @param traceFilePath the <b>relative path</b> of a PlanetLab Datacenter trace file.
* @param schedulingInterval the time interval in which precise utilization can be got from the file
* @throws NumberFormatException the number format exception
* @see #getSchedulingInterval()
*/
Expand All @@ -51,8 +62,8 @@ public static UtilizationModelPlanetLab getInstance(final String traceFilePath,
* Instantiates a new PlanetLab resource utilization model from a trace
* file.
*
* @param workloadFilePath The path of a PlanetLab Datacenter workload file.
* @param schedulingInterval the scheduling interval that defines the time interval in which precise utilization is be got
* @param workloadFilePath the path of a PlanetLab Datacenter workload file.
* @param schedulingInterval the time interval in which precise utilization can be got from the file
* @throws NumberFormatException the number format exception
* @see #getSchedulingInterval()
*/
Expand All @@ -65,11 +76,11 @@ public UtilizationModelPlanetLab(final String workloadFilePath, final double sch
* Instantiates a new PlanetLab resource utilization model with variable
* utilization samples from a workload file.
*
* @param workloadFilePath The path of a PlanetLab Datacenter workload file.
* @param schedulingInterval the scheduling interval that defines the time interval in which precise utilization is be got
* @param workloadFilePath the path of a PlanetLab Datacenter workload file.
* @param schedulingInterval the time interval in which precise utilization can be got from the file
* @param dataSamples number of samples to read from the workload file
* @throws NumberFormatException the number format exception
* @see #setSchedulingInterval(double)
* @see #getSchedulingInterval()
*/
public UtilizationModelPlanetLab(final String workloadFilePath, final double schedulingInterval, final int dataSamples) throws NumberFormatException
{
Expand All @@ -81,9 +92,10 @@ public UtilizationModelPlanetLab(final String workloadFilePath, final double sch
* utilization samples from a workload file.
*
* @param reader the {@link InputStreamReader} to read the workload file
* @param schedulingInterval the scheduling interval that defines the time interval in which precise utilization is be got
* @param schedulingInterval the time interval in which precise utilization can be got from the file
* @param dataSamples number of samples to read from the workload file
* @throws NumberFormatException the number format exception
* @see #getSchedulingInterval()
*/
private UtilizationModelPlanetLab(final InputStreamReader reader, final double schedulingInterval, final int dataSamples) throws NumberFormatException
{
Expand All @@ -110,13 +122,14 @@ private UtilizationModelPlanetLab(final InputStreamReader reader, final double s
* @throws IOException
*/
private double[] readWorkloadFile(final InputStreamReader reader, final int dataSamples) throws IOException {
Objects.requireNonNull(reader);
final double[] utilization = createEmptyArray(Math.max(2, dataSamples));

try (final BufferedReader input = new BufferedReader(reader)) {
final int n = utilization.length;
int i = 0;
String line;
while((line=input.readLine())!=null && i < n){
while((line=input.readLine())!=null && !line.startsWith("#") && i < n){
utilization[i++] = Integer.valueOf(line) / 100.0;
}
utilization[n - 1] = utilization[n - 2];
Expand All @@ -138,19 +151,19 @@ private double[] createEmptyArray(final int size) {
public double getUtilization(final double time) {
//If the time requested is multiple of the scheduling interval, gets a precise value from the trace utilization
if (time % getSchedulingInterval() == 0) {
return utilization[(int)getUtilizationIndex(time)];
return utilization[(int) getUtilizationIndex(time)];
}

/* Otherwise, computes a utilization based the
* utilization between the a interval [start - end] for which
* we have the utilization stored in the trace. */
* utilization between the a interval [start - end] for which
* we have the utilization stored in the trace. */
final int prevIndex = getPrevUtilizationIndex(time);

//elapsed time since the previous utilization index
//Elapsed time since the previous utilization index
final double elapsedTimeSincePrevUsage = prevIndex * getSchedulingInterval();

final double totalElapsedTime = time - elapsedTimeSincePrevUsage;
return utilization[prevIndex] + getUtilizationPerSec(time)*totalElapsedTime;
return utilization[prevIndex] + getUtilizationPerSec(time) * totalElapsedTime;
}

private double getUtilizationPerSec(final double time) {
Expand Down Expand Up @@ -239,6 +252,10 @@ public double getSchedulingInterval() {
* @see #getSchedulingInterval()
*/
public final void setSchedulingInterval(final double schedulingInterval) {
if(schedulingInterval <= 0){
throw new IllegalArgumentException("Scheduling interval must greater than 0. The given value is " + schedulingInterval);
}

this.schedulingInterval = schedulingInterval;
}
}
@@ -1,10 +1,10 @@
package org.cloudbus.cloudsim.utilizationmodels;

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class UtilizationModelPlanetLabTest {

/**
Expand All @@ -18,8 +18,7 @@ public class UtilizationModelPlanetLabTest {

@Before
public void setUp() {
utilizationModel = new UtilizationModelPlanetLab(getClass().getClassLoader()
.getResource(FILE).getPath(), SCHEDULING_INTERVAL);
utilizationModel = UtilizationModelPlanetLab.getInstance(FILE, SCHEDULING_INTERVAL);
}

@Test
Expand Down
11 changes: 11 additions & 0 deletions cloudsim-plus/src/test/resources/sample-planetlab-trace.dat
@@ -0,0 +1,11 @@
#A sample and synthetic PlanetLab file created for test purposes
10
20
30
40
50
60
70
80
90
100
3 changes: 2 additions & 1 deletion script/README.md
Expand Up @@ -6,5 +6,6 @@ This directory contains some scripts to automate some tasks.
Just run the script without parameters to see how to use.
- [install.sh](install.sh): Allows you to build all CloudSim Plus modules using maven and install them into the local maven repository, running
all tests (including Integration Tests). It doesn't require any parameter.
- [asciidoc.sh](asciidoc.sh): An experimental script that uses exports javadocs comments inside java source files to AsciiDoc format. It doesn't require any parameter.
- [asciidoc.sh](asciidoc.sh): An experimental script that exports javadocs comments inside java source files to AsciiDoc format. It doesn't require any parameter.
- [download-google-cluster-data.sh](download-google-cluster-data.sh): Downloads [Google Cluster Data](https://github.com/google/cluster-data/blob/master/ClusterData2011_2.md) trace files to be used to create simulations. Execute the script with `-h` argument to show usage help.

0 comments on commit fcf3796

Please sign in to comment.