Commit 31bac5e6 authored by Eduardo Falcão's avatar Eduardo Falcão
Browse files

Merge branch 'resource-provisioned-shared' into 'development'

merging Resource provisioned shared branch into development

See merge request lenovo-autonomic/cloudsimplus!11
parents e14d9e54 c387e015
/*
* 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.cloudbus.cloudsim.examples.autonomics;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicy;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicySimple;
import org.cloudbus.cloudsim.allocationpolicies.migration.VmAllocationPolicyMigrationWorstFitStaticThreshold;
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.power.models.PowerModelLinear;
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerShared;
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.VmSchedulerSpaceShared;
import org.cloudbus.cloudsim.schedulers.vm.VmSchedulerTimeShared;
import org.cloudbus.cloudsim.selectionpolicies.power.PowerVmSelectionPolicyMinimumUtilization;
import org.cloudbus.cloudsim.util.Log;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelDynamic;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelFull;
import org.cloudbus.cloudsim.vms.Vm;
import org.cloudbus.cloudsim.vms.VmSimple;
import org.cloudsimplus.slametrics.SLAMonitor;
import org.cloudsimplus.slametrics.SlaContract;
import org.cloudsimplus.builders.tables.CloudletsTableBuilder;
/**
* This example shows how to detect SLA violation from IOPS perspective.
*
* @author eduardolfalcao
*/
public final class IoMetricBeingViolatedExample {
private static final int SCHEDULE_TIME_TO_PROCESS_DATACENTER_EVENTS = 1;
private static final int HOST_MIPS_BY_PE = 1000;
private static final int HOST_NUMBER_OF_PES = 3;
private static final long HOST_RAM = 500000; //host memory (MB)
private static final long HOST_STORAGE = 1000000; //host storage
private static final long HOST_BW = 100000000L;
private static final long HOST_IOPS = 1000; //host io capacity
private static final int VM_MIPS = 1000;
private static final long VM_SIZE = 1000; //image size (MB)
private static final int VM_RAM = 10000; //vm memory (MB)
private static final long VM_BW = 100000;
private static final int VM_PES_NUM = 1; //number of cpus
private static final long VM_IOPS = 500;
private static final long CLOUDLET_LENGHT = 20000;
private static final long CLOUDLET_FILESIZE = 300;
private static final long CLOUDLET_OUTPUTSIZE = 300;
private static final int NUMBER_OF_HOSTS_TO_CREATE = 1;
private static final int NUMBER_OF_VMS_TO_CREATE = NUMBER_OF_HOSTS_TO_CREATE*3;
private static final int NUMBER_OF_CLOUDLETS_TO_CREATE_BY_VM = 1;
private final List<Vm> vmlist = new ArrayList<>();
private CloudSim simulation;
/**
* The file containing the SLA Contract in JSON format.
*/
public static final String METRICS_FILE = "src/main/resources/SlaCustomerAutonomics.json";
private SlaContract contract;
public static void main(String[] args) throws FileNotFoundException, IOException {
new IoMetricBeingViolatedExample();
}
private List<Cloudlet> cloudletList;
public IoMetricBeingViolatedExample() throws FileNotFoundException, IOException {
Log.printConcatLine("Starting ", IoMetricBeingViolatedExample.class.getSimpleName(), "...");
simulation = new CloudSim();
this.contract = SlaContract.getInstance(METRICS_FILE);
cloudletList = new ArrayList<>(NUMBER_OF_CLOUDLETS_TO_CREATE_BY_VM);
@SuppressWarnings("unused")
Datacenter datacenter0 = createDatacenter();
DatacenterBroker broker = new DatacenterBrokerSimple(simulation);
createAndSubmitVms(broker);
createAndSubmitCloudlets(broker);
simulation.start();
cpuUtilization(cloudletList);
new CloudletsTableBuilder(broker.getCloudletFinishedList()).build();
Log.printConcatLine(IoMetricBeingViolatedExample.class.getSimpleName(), " finished!");
for(int time = 0; time < simulation.clock(); time++){
for(Vm vm : this.vmlist){
System.out.println("Time: "+time+", vm: "+vm.getId()+" - violation = "+SLAMonitor.isTheIopsSlaBeingViolated(vm, time));
}
}
}
public void createAndSubmitCloudlets(DatacenterBroker broker) {
UtilizationModel utilizationModelFull = new UtilizationModelFull();
final int numberOfCloudlets = NUMBER_OF_VMS_TO_CREATE;
for (int i = 0; i < numberOfCloudlets; i++) {
Vm hostingVm = vmlist.get(i);
Cloudlet c = new CloudletSimple(
hostingVm.getId() + i, CLOUDLET_LENGHT, 2)
.setFileSize(CLOUDLET_FILESIZE)
.setOutputSize(CLOUDLET_OUTPUTSIZE)
.setUtilizationModelCpu(utilizationModelFull)
.setUtilizationModelRam(utilizationModelFull)
.setUtilizationModelBw(utilizationModelFull)
.setUtilizationModelIops(utilizationModelFull);
cloudletList.add(c);
broker.bindCloudletToVm(c, hostingVm);
}
broker.submitCloudletList(cloudletList);
}
public void createAndSubmitVms(DatacenterBroker broker) {
for (int i = 0; i < NUMBER_OF_VMS_TO_CREATE; i++) {
Vm vm = createVm(broker);
vmlist.add(vm);
}
broker.submitVmList(vmlist);
}
/**
*
* @param broker
* @return
*/
public Vm createVm(DatacenterBroker broker) {
VmSimple vm = new VmSimple(vmlist.size(), VM_MIPS, VM_PES_NUM);
vm.setContract(contract);
vm.setRam(VM_RAM).setBw(VM_BW).setIops(VM_IOPS).setSize(VM_SIZE)
.setCloudletScheduler(new CloudletSchedulerTimeShared());
vm.getUtilizationHistory().enable();
Log.printConcatLine(
"#Requested creation of VM ", vm.getId(), " with ", VM_MIPS, " MIPS x ", VM_PES_NUM);
return vm;
}
private Datacenter createDatacenter() {
final List<Host> hostList = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_HOSTS_TO_CREATE; i++) {
hostList.add(createHost(i, HOST_NUMBER_OF_PES, HOST_MIPS_BY_PE));
Log.printConcatLine("#Created host ", i, " with ", HOST_MIPS_BY_PE, " mips x ", HOST_NUMBER_OF_PES);
}
Log.printLine();
VmAllocationPolicy allocationPolicy = new VmAllocationPolicySimple();
DatacenterSimple dc = new DatacenterSimple(simulation, hostList, allocationPolicy);
dc.enableMigrations().setSchedulingInterval(SCHEDULE_TIME_TO_PROCESS_DATACENTER_EVENTS);
return dc;
}
/**
*
* @param id
* @param numberOfPes
* @param mipsByPe
* @return
*
* @todo @author manoelcampos Using the {@link VmSchedulerSpaceShared} its
* getting NullPointerException, probably due to lack of CPU for all VMs. It
* has to be created an IT test to check this problem.
*
* @todo @author manoelcampos The method
* {@link DatacenterBroker#getCloudletFinishedList()} returns an empty list
* when using {@link DatacenterSimple},
* {@link Host} and {@link Vm}.
*/
public static Host createHost(int id, int numberOfPes, long mipsByPe) {
List<Pe> peList = createPeList(numberOfPes, mipsByPe);
Host host = new HostSimple(HOST_RAM, HOST_IOPS, HOST_BW, HOST_STORAGE, peList);
host.setPowerModel(new PowerModelLinear(1000, 0.7))
.setRamProvisioner(new ResourceProvisionerSimple())
.setBwProvisioner(new ResourceProvisionerSimple())
.setIopsProvisioner(new ResourceProvisionerShared())
.setVmScheduler(new VmSchedulerSpaceShared()); //FIXME SpaceShared may have a bug
host.enableStateHistory();
return host;
}
public static List<Pe> createPeList(int numberOfPEs, long mips) {
List<Pe> list = new ArrayList<>(numberOfPEs);
for (int i = 0; i < numberOfPEs; i++) {
list.add(new PeSimple(mips, new PeProvisionerSimple()));
}
return list;
}
/**
* Shows the cpu utilization
*
* @param cloudlet to calculate the utilization
* @return cpuUtilization
*/
private void cpuUtilization(List<Cloudlet> cloudlet) {
double cpuTime = 0;
for (Cloudlet cloudlets : cloudlet) {
cpuTime += cloudlets.getActualCpuTime();
}
Log.printFormattedLine("\n #Cpu utilization -> %f", (cpuTime * 100) / 100);
}
}
......@@ -132,10 +132,11 @@ public class VmsCpuUsageExample {
long bw = 1000;
//create two VMs
Vm vm = new VmSimple(id, mips, pesNumber);
VmSimple vm = new VmSimple(id, mips, pesNumber);
vm.setRam(ram).setBw(bw)
.setSize(size)
.setCloudletScheduler(new CloudletSchedulerTimeShared());
vm.getUtilizationHistory().enable();
return vm;
}
......@@ -144,7 +145,7 @@ public class VmsCpuUsageExample {
int numberOfUsageHistoryEntries = 0;
for (Vm vm : vmlist) {
Log.printFormattedLine("VM %d", vm.getId());
if (vm.getStateHistory().isEmpty()) {
if (vm.getUtilizationHistory().getHistory().isEmpty()) {
Log.printLine("\tThere isn't any usage history");
continue;
}
......@@ -187,7 +188,7 @@ public class VmsCpuUsageExample {
hostList.add(host);
}
return new DatacenterSimple(simulation, hostList, new VmAllocationPolicySimple());
return new DatacenterSimple(simulation, hostList, new VmAllocationPolicySimple()).setSchedulingInterval(1);
}
private static Host createHost(int pesNumber, long mips, int hostId) {
......@@ -201,9 +202,12 @@ public class VmsCpuUsageExample {
long storage = 1000000; //host storage
int bw = 10000;
return new HostSimple(ram, bw, storage, peList)
.setRamProvisioner(new ResourceProvisionerSimple())
.setBwProvisioner(new ResourceProvisionerSimple())
.setVmScheduler(new VmSchedulerTimeShared());
Host h = new HostSimple(ram, bw, storage, peList)
.setRamProvisioner(new ResourceProvisionerSimple())
.setBwProvisioner(new ResourceProvisionerSimple())
.setVmScheduler(new VmSchedulerTimeShared());
h.enableStateHistory();
return h;
}
}
{
"metrics": [
{
"name": "IOPSProvisioned",
"dimensions": [
{
"name": "minValue",
"value": 1000,
"unit": "Iops"
}
]
}
]
}
\ No newline at end of file
......@@ -111,7 +111,8 @@ public final class VmMigrationWhenCpuMetricIsViolatedExample {
/**
* The file containing the SLA Contract in JSON format.
*/
public static final String METRICS_FILE = "SlaMetrics.json";
// public static final String METRICS_FILE = "SlaMetrics.json";
public static final String METRICS_FILE = "SlaCustomer0.json";
private SlaContract contract;
......
......@@ -374,6 +374,7 @@ public abstract class DatacenterBrokerAbstract extends CloudSimEntity implements
setSimulationForUtilizationModelIfNotSet(c.getUtilizationModelCpu());
setSimulationForUtilizationModelIfNotSet(c.getUtilizationModelBw());
setSimulationForUtilizationModelIfNotSet(c.getUtilizationModelRam());
setSimulationForUtilizationModelIfNotSet(c.getUtilizationModelIops());
}
}
......
......@@ -184,7 +184,7 @@ public class CloudSim implements Simulation {
// NOTE: the order for the lines below is important
this.calendar = Calendar.getInstance();
this.cis = new CloudInformationService(this);
this.cis = new CloudInformationService(this);
if (minTimeBetweenEvents <= 0) {
throw new IllegalArgumentException("The minimal time between events should be positive, but is:" + minTimeBetweenEvents);
......
......@@ -971,11 +971,16 @@ public class HostSimple implements Host {
"%.2f: [%s] %.0f MIPS not allocated for each one of the %d PEs from %s due to %s.",
getSimulation().clock(), this, notAllocatedMipsByPe, vm.getNumberOfPes(), vm, reason);
}
double totalAllocatedIops = iopsProvisioner.getAllocatedResourceForVm(vm);
double totalRequestedIops = vm.getCurrentRequestedIops();
final VmStateHistoryEntry entry = new VmStateHistoryEntry(
currentTime,
totalAllocatedMips,
totalRequestedMips,
totalAllocatedIops,
totalRequestedIops,
vm.isInMigration() && !getVmsMigratingIn().contains(vm));
vm.addStateHistoryEntry(entry);
......
......@@ -63,7 +63,7 @@ public class ResourceProvisionerShared extends ResourceProvisionerAbstract {
}
if(isPreemptionNeeded(vm, newTotalVmResourceCapacity)){
//allocate resources equally
allocateResourcesEqually(vm,newTotalVmResourceCapacity); //allocate resources equally
return true;
}
else{
......@@ -88,9 +88,7 @@ public class ResourceProvisionerShared extends ResourceProvisionerAbstract {
getResourceAllocationMap().put(vm, newTotalVmResourceCapacity);
vm.getResource(getResourceClass()).setAllocatedResource(prevVmResourceAllocation);
return true;
}
}
}
@Override
......@@ -212,14 +210,14 @@ public class ResourceProvisionerShared extends ResourceProvisionerAbstract {
Iterator<VmRequestedAllocated> it = vmRequestedAndAllocatedList.listIterator();
while (it.hasNext() && available > 0) {
VmRequestedAllocated vra = it.next();
long toBeAllocated = Math.min(vra.getRequested(), available); //gets the minimum between minimum requested value and available resources
if(toBeAllocated*vmRequestedAndAllocatedList.size() < available){ //then allocates it to each vm (if possible)
long toBeAllocated = Math.min(vra.getRequested(), available); //gets the minimum between minimum requested value and available resources
if(toBeAllocated*vmRequestedAndAllocatedList.size() < available){ //then allocates it to each vm (if possible)
Iterator<VmRequestedAllocated> it2 = vmRequestedAndAllocatedList.listIterator();
while (it2.hasNext()) {
VmRequestedAllocated vra2 = it2.next();
vra2.addAllocated(toBeAllocated); //increase the current allocation by the requested value
vra2.subtractRequested(toBeAllocated); //and subtract the current requested by the recently allocated value
if(vra2.getRequested() == 0){ //if this vm is satisfied
if(vra2.getRequested() == 0){ //if this vm is satisfied
finalList.add(vra2); //add it on final list
it2.remove(); //and remove from the main list
}
......@@ -233,20 +231,30 @@ public class ResourceProvisionerShared extends ResourceProvisionerAbstract {
VmRequestedAllocated vra2 = it2.next();
vra2.addAllocated(toBeAllocated); //increase the current allocation by the requested value
vra2.subtractRequested(toBeAllocated); //and subtract the current requested by the recently allocated value
finalList.add(vra2); //add it on final list because its the final allocation
it2.remove(); //and remove from the main list
finalList.add(vra2); //add it on final list because its the final allocation
it2.remove(); //and remove from the main list
allocated += toBeAllocated; //updates allocated and available
available -= toBeAllocated;
}
}
Collections.sort(vmRequestedAndAllocatedList); //is it necessary?
it = vmRequestedAndAllocatedList.listIterator(); //update iterator with new state of the list
}
}
deallocateResourceForAllVms();
for(VmRequestedAllocated vra : finalList){
//Allocates the requested resource from the physical resource
getResource().allocateResource(vra.getAllocated());
getResourceAllocationMap().put(vra.getVm(), vra.getAllocated());
vm.getResource(getResourceClass()).setAllocatedResource(vra.getAllocated());
}
}
@Override
public boolean isSuitableForVm(final Vm vm, final long newVmTotalAllocatedResource) {
return getResourceAllocationMap().size() < getResource().getCapacity();
int tam = getResourceAllocationMap().size();
long cap = getResource().getCapacity();
return tam < cap;
}
/**
......@@ -258,95 +266,7 @@ public class ResourceProvisionerShared extends ResourceProvisionerAbstract {
private boolean isPreemptionNeeded(final Vm vm, final long newVmTotalAllocatedResource) {
final long currentAllocatedResource = getAllocatedResourceForVm(vm);
final long allocationDifference = newVmTotalAllocatedResource - currentAllocatedResource;
return getResource().getAvailableResource() >= allocationDifference;
return getResource().getAvailableResource() < allocationDifference;
}
// private void allocateResourcesEquallyBKUP(final Vm vm, final long newTotalVmResourceCapacity){
//
// Map<Long,List<Vm>> requestedPerVm = new TreeMap<Long,List<Vm>>();
// Map<Vm,Long> resourcesToBeAllocated = new HashMap<Vm,Long>(); //the final allocation map
//
// for(Entry<Vm, Long> entry : getResourceAllocationMap().entrySet()){
// resourcesToBeAllocated.put(entry.getKey(), 0L); //initially the resourcesToBeAllocated of each VM is 0
// if(!requestedPerVm.containsKey(entry.getValue())){
// requestedPerVm.put(entry.getValue(), new ArrayList<Vm>());
// }
// requestedPerVm.get(entry.getValue()).add(entry.getKey()); //fulfill the requestedPerVm map with values from resourceAllocationMap
// }
//
// long capacity = getResource().getCapacity();
// long allocated = 0L;
// long available = capacity;
//
// int numVms = resourcesToBeAllocated.size();
//
// /**
// * here we iterate over requestedPerVm map distributing the available resources equally
// */
// Iterator<Map.Entry<Long,List<Vm>>> it = requestedPerVm.entrySet().iterator();
// while (it.hasNext()) {
// Map.Entry<Long,List<Vm>> entry = it.next();
// long requested = entry.getKey(); //gets the minimum requested value and
// if(requested*numVms<available){ //then allocates it to each vm (if possible)
// for (Map.Entry<Vm,Long> entryAllocation : resourcesToBeAllocated.entrySet()) {
// entryAllocation.setValue(entryAllocation.getValue()+requested); //increase the current allocation by the requested value
// Iterator<Map.Entry<Long,List<Vm>>> it2 = requestedPerVm.entrySet().iterator(); //and then subtract this value in requestedPerVm for all occurrences
// while (it2.hasNext()) { //as long as we have a map we need to use an iterator to remove
// Map.Entry<Long,List<Vm>> entry2 = it2.next();
// long entry2requested = entry2.getKey();
// if(entry2requested-requested==0){ //if this current allocation fulfills the requirements
// if(entry2.getValue().size()==1){ //and if there's only one VM with this requested
// it2.remove(); //then, remove this entry from requestedPerVm
// } else{ //otherwise, there is/are more VM(s) requesting this same amount
// Iterator<Vm> it3 = entry2.getValue().listIterator();
// while (it3.hasNext()) {
//
// }
// //entry2.getValue().remove(entryAllocation.getKey());
// }
// } else{
// if(!requestedPerVm.containsKey(entry2requested-requested)){ //if there is no other VM with this amount of request, then just put this new value in map
// requestedPerVm.put(entry2requested-requested, entry2.getValue());
// } else{ //if there is other VM with this amount of request, then add this VM on the list (inside map)
// requestedPerVm.get(entry.getKey()).add(e)
// }
// it2.remove();
// }
// }
// }
// allocated += requested*numVms;
// available = capacity - allocated;
// it.remove();
// } else{
//
// }
// }
//basically chooses the vm with less resources requested and give this amount to all Vms
//keep doing it until all you can not allocate resources equally to the VMs
//after this, split the remaining resources and give to th remaininh VMs
// int numberOfVms = getResourceAllocationMap().size();
// if(!getResourceAllocationMap().containsKey(vm))
// numberOfVms++;
//
// long resourcesPerVm = getResource().getCapacity()/numberOfVms;
//
//
//
//
// long resourcesMissingToAllocate = resourcesPerVm - (newTotalVmResourceCapacity - getResource().getAvailableResource());
//
//
// for(Entry<Vm, Long> entry : getResourceAllocationMap().entrySet()){
// if(entry.getValue().longValue() > resourcesPerVm){
// getResource().allocateResource(amountToAllocate)
// }
// }
// getResourceAllocationMap();
// int numberOfVms
// getResourceAllocationMap()
}
......@@ -1037,9 +1037,9 @@ public abstract class CloudletSchedulerAbstract implements CloudletScheduler {
public double getCurrentRequestedIopsPercentUtilization() {
return cloudletExecList.stream()
.map(CloudletExecution::getCloudlet)
.map(Cloudlet::getUtilizationModelIops) //TODO Implement getUtilizationModelIops
.map(Cloudlet::getUtilizationModelIops)
.mapToDouble(um -> getAbsoluteCloudletResourceUtilization(um, vm.getIops().getCapacity()))
.sum() / vm.getBw().getCapacity();
.sum() / vm.getIops().getCapacity();
}
@Override
......
......@@ -17,13 +17,15 @@ import org.cloudbus.cloudsim.resources.*;
import org.cloudbus.cloudsim.schedulers.cloudlet.CloudletScheduler;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import org.cloudbus.cloudsim.core.CustomerEntity;
import org.cloudbus.cloudsim.core.CustomerEntity;
import org.cloudsimplus.autoscaling.VerticalVmScaling;
import org.cloudsimplus.listeners.VmHostEventInfo;