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

Merge branch 'sla-monitor' into 'development'

merging Sla monitor into development

See merge request lenovo-autonomic/cloudsimplus!13
parents f6c99f28 d7acc47f
......@@ -81,7 +81,7 @@ public final class IoMetricBeingViolatedExample {
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 VM_IOPS = 300;
private static final long CLOUDLET_LENGHT = 20000;
private static final long CLOUDLET_FILESIZE = 300;
......@@ -132,7 +132,7 @@ public final class IoMetricBeingViolatedExample {
Log.printConcatLine(IoMetricBeingViolatedExample.class.getSimpleName(), " finished!");
for(int time = 0; time < simulation.clock(); time++){
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));
}
......
......@@ -58,6 +58,7 @@ 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.ResourceProvisionerShared;
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple;
import org.cloudbus.cloudsim.resources.Pe;
import org.cloudbus.cloudsim.resources.PeSimple;
......@@ -115,7 +116,7 @@ public final class MigrationExample1 {
private static final int SCHEDULE_INTERVAL = 5;
private static final int HOSTS = 5;
private static final int VMS = 3;
private static final int VMS = 10;
private static final int HOST_MIPS = 1000; //for each PE
......@@ -145,7 +146,7 @@ public final class MigrationExample1 {
* The percentage of host CPU usage that trigger VM migration
* due to over utilization (in scale from 0 to 1, where 1 is 100%).
*/
private static final double HOST_UTILIZATION_THRESHOLD_FOR_VM_MIGRATION = 0.7;
private static final double HOST_UTILIZATION_THRESHOLD_FOR_VM_MIGRATION = 1;
private static final int VM_MIPS = 1000; //for each PE
private static final long VM_SIZE = 1000; //image size (MB)
......
......@@ -5,7 +5,7 @@
"dimensions": [
{
"name": "minValue",
"value": 1000,
"value": 340,
"unit": "Iops"
}
]
......
......@@ -7,17 +7,20 @@
*/
package org.cloudbus.cloudsim.allocationpolicies.migration;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicy;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.selectionpolicies.power.PowerVmSelectionPolicy;
import org.cloudbus.cloudsim.vms.Vm;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicy;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.selectionpolicies.power.PowerVmSelectionPolicy;
import org.cloudbus.cloudsim.vms.Vm;
/**
* A {@link VmAllocationPolicy} that uses a Static CPU utilization Threshold (THR) to
* detect host {@link #getUnderUtilizationThreshold() under} and
......@@ -72,6 +75,21 @@ public class VmAllocationPolicyMigrationBestFitStaticThreshold extends VmAllocat
protected Optional<Host> findHostForVmInternal(final Vm vm, final Stream<Host> hostStream) {
/*It's ignoring the super class to intentionally avoid the additional filtering performed there
* and to apply a different method to select the Host to place the VM.*/
// Iterator<Host> itH = hostStream.iterator();
// Host maxHost = null;
// while(itH.hasNext()){
// Host h = itH.next();
// System.out.println("Host "+h.getId()+": "+h.getUtilizationOfCpuMips());
// if(maxHost == null)
// maxHost = h;
// else if(h.getUtilizationOfCpuMips()>maxHost.getUtilizationOfCpuMips())
// maxHost = h;
// }
//
//
//// Optional<Host> h = hostStream.max(Comparator.comparingDouble(Host::getUtilizationOfCpuMips));
// return Optional.of(maxHost);
return hostStream.max(Comparator.comparingDouble(Host::getUtilizationOfCpuMips));
}
}
package org.cloudbus.cloudsim.allocationpolicies.migration;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicy;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicyAbstract;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.util.Log;
import org.cloudbus.cloudsim.provisioners.ResourceProvisioner;
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerShared;
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple;
import org.cloudbus.cloudsim.selectionpolicies.power.PowerVmSelectionPolicy;
import org.cloudbus.cloudsim.vms.Vm;
import org.cloudsimplus.slametrics.SLAMonitor;
import org.cloudbus.cloudsim.core.Machine;
import org.cloudbus.cloudsim.core.Simulation;
import org.cloudbus.cloudsim.datacenters.Datacenter;
import static java.util.Comparator.comparingDouble;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
/**
* A VM allocation policy that tries to exploit a VM's SLA to
* better use the resources of a host, reducing fragmentation.
*
* To accomplish this task, the allocation policy continually
* keeps track of all VMs and migrate them from hosts in which
* the SLA contracted is delivered (SL Loose) to hosts in which
* the instantaneous SLA may de be violated (SL Tight), or vice-
* versa.
*
* For more information, please refer to this paper:
*
* @author Kaio Kassiano Moura Oliveira (@kaiokmo)
* @author Eduardo de Lucena Falcao (@eduardolfalcao)
*/
public class VmAllocationPolicyMigrationSla extends VmAllocationPolicyAbstract {
private static final String LOOSE = "LOOSE";
private static final String TIGHT = "TIGHT";
private static final Double IMPRECISION = 0.001;
private final int MIGRATION_TIME;
private VmAllocationPolicy allocationPolicy;
/**
* A map between a Host and its previous fragmentation.
*/
private Map<Host, Double> previousFragmentation;
/**
* A map between a Host and its current fragmentation.
*/
private Map<Host, Double> currentFragmentation;
public VmAllocationPolicyMigrationSla(VmAllocationPolicy allocationPolicy, int migrationTime) {
this.allocationPolicy = allocationPolicy;
this.MIGRATION_TIME = migrationTime;
this.previousFragmentation = new HashMap<Host, Double>();
this.currentFragmentation = new HashMap<Host, Double>();
}
@Override
public Map<Vm, Host> getOptimizedAllocationMap(
final List<? extends Vm> vmList) {
if(currentFragmentation.isEmpty()){
for(Host h : getDatacenter().getHostList()){
double hostFragmentation = getFragmentation(h);
currentFragmentation.put(h, hostFragmentation);
previousFragmentation.put(h, hostFragmentation);
}
return new HashMap<Vm, Host>();
}
//filter heaven hosts
List<Host> looseSlaHosts = getHostsWithLooseSla();
//get all vms from heaven hosts and sort vms from higher to lower fragmentation
List<Vm> vmsDescendingFragmentation = new ArrayList<Vm>();
vmsDescendingFragmentation.addAll(getVmsWithEnoughCredit(looseSlaHosts));
sort(vmsDescendingFragmentation);
//filter hell hosts and sort hell hosts ascending by fragmentation
List<Host> tightSlaHosts = getHostsWithTightSla();
sort(tightSlaHosts);
//update current fragmentation
for(Host h : getDatacenter().getHostList()){
double hostFragmentation = getFragmentation(h);
currentFragmentation.put(h, hostFragmentation);
}
Map<Vm, Host> migrationMap = new HashMap<Vm, Host>();
//for each hell host
for(Host h : tightSlaHosts){
//get those with stable fragmentation degree
if(vmsDescendingFragmentation.isEmpty()){
break;
}
if(Math.abs(currentFragmentation.get(h) - previousFragmentation.get(h)) < IMPRECISION){
//and try to allocate a VM from the list
Iterator<Vm> vmIterator = vmsDescendingFragmentation.iterator();
while(vmIterator.hasNext()){
Vm vm = vmIterator.next();
if(h.addMigratingInVm(vm)){
migrationMap.put(vm, h);
vmIterator.remove();
}
}
}
}
//TODO and from hell to heaven??
previousFragmentation.putAll(currentFragmentation);
return migrationMap;
}
/**
* Sorts a list of VMs from high to low fragmentation,
* or a list of hosts from low to high fragmentation
* @param list a list of Machines (vms or hosts)
*/
protected void sort(List<? extends Machine> list){
if(list == null || list.isEmpty())
return;
Comparator<Machine> comparator = null;
if(list.get(0) instanceof Vm){
comparator = new Comparator<Machine>() {
@Override
public int compare(Machine m1, Machine m2) {
Vm vm1 = (Vm) m1;
Vm vm2 = (Vm) m2;
double fragmentationVm1 = getFragmentation(vm1);
double fragmentationVm2 = getFragmentation(vm2);
if(fragmentationVm1 == fragmentationVm2)
return 0;
else if(fragmentationVm1 < fragmentationVm2)
return 1;
else
return -1;
}
};
}
else{
comparator = new Comparator<Machine>() {
@Override
public int compare(Machine m1, Machine m2) {
Host h1 = (Host) m1;
Host h2 = (Host) m2;
double fragmentationH1 = getFragmentation(h1);
double fragmentationH2 = getFragmentation(h2);
if(fragmentationH1 == fragmentationH2)
return 0;
else if(fragmentationH1 < fragmentationH2)
return -1;
else
return 1;
}
};
}
Collections.sort(list,comparator);
}
/**
* Get candidate Vms with enough credit to go to a best effort host.
* @param h the host
* @return a list of VMs
*/
protected List<Vm> getVmsWithEnoughCredit(List<Host> looseSlaHosts){
List<Vm> candidateVmsToMigrate = new ArrayList<Vm>();
final double clock = getDatacenter().getSimulation().clock();
for (Host h : looseSlaHosts) {
for (Vm vm : h.getVmList()) {
if (SLAMonitor.getVmViolationTime(vm, clock) + MIGRATION_TIME <=
SLAMonitor.getMaximumAllowedSlaViolationTime(vm)) {
candidateVmsToMigrate.add(vm);
}
}
}
return candidateVmsToMigrate;
}
/**
* Returns the absolute fragmentation (amount of idle resources)
* of a machine, be it a VM or a Host.
* @param m the machine
* @return the fragmentation
*/
protected double getFragmentation(Machine m){
return m.getIops().getAvailableResource();
}
/**
* Get all the Vms suffering in hell, i.e., VMs that are about to
* violate the overall SLA.
* @param host a tight SLA host
* @return a set of VMs
*/
protected Set<Vm> getSufferingVms(Set<Host> tightSlaHosts){
Set<Vm> sufferingVms = new HashSet<Vm>();
final double clock = getDatacenter().getSimulation().clock();
for (Host h : tightSlaHosts) {
for (Vm vm : h.getVmList()) {
if (SLAMonitor.getVmViolationTime(vm, clock) + MIGRATION_TIME >=
SLAMonitor.getMaximumAllowedSlaViolationTime(vm)) {
sufferingVms.add(vm);
}
}
}
return sufferingVms;
}
/**
* Get hosts in which the SLA are delivered with no performance degradation.
* @return a set of hosts
*/
protected List<Host> getHostsWithTightSla(){
return getHostsFromSlaExploitationPolicy(getDatacenter(), TIGHT);
}
/**
* Get hosts in which the SLA are delivered in a best effort scenario.
* (may have (or not) performance degradation)
* @return a set of hosts
*/
protected List<Host> getHostsWithLooseSla(){
return getHostsFromSlaExploitationPolicy(getDatacenter(), LOOSE);
}
/**
* Get hosts with a given SlaExploitationPolicy (loose or tight).
* @param dc Datacenter to get hosts from
* @param policyType type scenario of the host SlaExplotation
* @return a set of hosts
*/
private List<Host> getHostsFromSlaExploitationPolicy(Datacenter dc, String policyType) {
List<Host> hosts = new ArrayList<Host>();
for (Host host : dc.getHostList()) {
if (policyType.toUpperCase().equals(LOOSE) &&
host.getIopsProvisioner() instanceof ResourceProvisionerSimple) {
hosts.add(host);
}
else if (policyType.toUpperCase().equals(TIGHT) &&
host.getIopsProvisioner() instanceof ResourceProvisionerShared) {
hosts.add(host);
}
}
return hosts;
}
@Override
public Optional<Host> findHostForVm(Vm vm) {
return allocationPolicy.findHostForVm(vm);
}
public int getMIGRATION_TIME() {
return MIGRATION_TIME;
}
}
......@@ -61,16 +61,6 @@ public class HostSimple implements Host {
private final Iops iops;
private final Bandwidth bw;
/**
* @see #getAllocatedBw()
*/
private long allocatedBw;
private final long allocatedRam;
private long allocatedIops;
/**
* @see #getStorage()
......@@ -161,9 +151,6 @@ public class HostSimple implements Host {
this.setId(-1);
this.setActive(true);
this.setSimulation(Simulation.NULL);
this.allocatedRam = ram;
this.allocatedBw = bw;
this.ram = new Ram(ram);
this.bw = new Bandwidth(bw);
......@@ -188,16 +175,10 @@ public class HostSimple implements Host {
}
//FIXME create two constructors?
public HostSimple(final long ram, final long iops, final long bw, final long storage, final List<Pe> peList) {
this.setId(-1);
this.setActive(true);
this.setSimulation(Simulation.NULL);
this.allocatedRam = ram;
this.allocatedIops = iops;
this.allocatedBw = bw;
this.ram = new Ram(ram);
this.bw = new Bandwidth(bw);
......@@ -341,6 +322,14 @@ public class HostSimple implements Host {
msg, vm, this, vm.getBw().getCapacity(), bw.getAvailableResource());
return false;
}
if (!iopsProvisioner.isSuitableForVm(vm, vm.getCurrentRequestedIops())) {
Log.printFormattedLine(
"%.2f: %s: [%s] Allocation of %s to %s failed due to lack of IOPS. Required %d but there is just %d iops available.",
simulation.clock(), getClass().getSimpleName(),
msg, vm, this, vm.getIops().getCapacity(), iops.getAvailableResource());
return false;
}
if (!vmScheduler.isSuitableForVm(vm)) {
Log.printFormattedLine(
......@@ -356,6 +345,7 @@ public class HostSimple implements Host {
storage.allocateResource(vm.getStorage());
ramProvisioner.allocateResourceForVm(vm, vm.getCurrentRequestedRam());
bwProvisioner.allocateResourceForVm(vm, vm.getCurrentRequestedBw());
iopsProvisioner.allocateResourceForVm(vm, vm.getCurrentRequestedIops());
vmScheduler.allocatePesForVm(vm, vm.getCurrentRequestedMips());
return true;
......@@ -369,6 +359,7 @@ public class HostSimple implements Host {
}
ramProvisioner.allocateResourceForVm(vm, vm.getCurrentRequestedRam());
bwProvisioner.allocateResourceForVm(vm, vm.getCurrentRequestedBw());
iopsProvisioner.allocateResourceForVm(vm, vm.getCurrentRequestedIops());
vmScheduler.allocatePesForVm(vm, vm.getCurrentRequestedMips());
storage.allocateResource(vm.getStorage());
}
......@@ -380,7 +371,8 @@ public class HostSimple implements Host {
vmScheduler.getPeCapacity() >= vm.getCurrentRequestedMaxMips() &&
vmScheduler.getAvailableMips() >= vm.getCurrentRequestedTotalMips() &&
ramProvisioner.isSuitableForVm(vm, vm.getCurrentRequestedRam()) &&
bwProvisioner.isSuitableForVm(vm, vm.getCurrentRequestedBw());
bwProvisioner.isSuitableForVm(vm, vm.getCurrentRequestedBw()) &&
iopsProvisioner.isSuitableForVm(vm, vm.getCurrentRequestedIops());
}
@Override
......@@ -421,6 +413,7 @@ public class HostSimple implements Host {
vm.setCreated(false);
ramProvisioner.deallocateResourceForVm(vm);
bwProvisioner.deallocateResourceForVm(vm);
iopsProvisioner.deallocateResourceForVm(vm);
vmScheduler.deallocatePesFromVm(vm);
storage.deallocateResource(vm.getStorage());
}
......@@ -442,6 +435,7 @@ public class HostSimple implements Host {
protected void deallocateResourcesOfAllVms() {
ramProvisioner.deallocateResourceForAllVms();
bwProvisioner.deallocateResourceForAllVms();
iopsProvisioner.deallocateResourceForAllVms();
vmScheduler.deallocatePesForAllVms();
}
......@@ -799,7 +793,7 @@ public class HostSimple implements Host {
@Override
public List<ResourceManageable> getResources() {
if(simulation.isRunning() && resources.isEmpty()){
resources = Arrays.asList(ramProvisioner.getResource(), bwProvisioner.getResource());
resources = Arrays.asList(ramProvisioner.getResource(), bwProvisioner.getResource(), iopsProvisioner.getResource());
}
return Collections.unmodifiableList(resources);
}
......@@ -807,7 +801,7 @@ public class HostSimple implements Host {
@Override
public ResourceProvisioner getProvisioner(final Class<? extends ResourceManageable> resourceClass) {
if(simulation.isRunning() && provisioners.isEmpty()){
provisioners = Arrays.asList(ramProvisioner, bwProvisioner);
provisioners = Arrays.asList(ramProvisioner, bwProvisioner, iopsProvisioner);
}
return provisioners
......@@ -1024,11 +1018,15 @@ public class HostSimple implements Host {
final double requestedMips,
final boolean isActive)
{
Log.printLine("Time: " + time);
Log.printLine("Time: " + time+" - host "+getId());
Log.printLine("AllocatedMips: " + allocatedMips);
Log.printLine("RequestedMips: " + requestedMips);
Log.printLine("AllocatedIops: " + getAllocatedIops());
Log.printLine("RequestedIops: " + getRequestedIops());
Log.printLine("AllocatedRam: " + getAllocatedRam());
Log.printLine("RequestedRam: " + getRequestedRam());
Log.printLine("AllocatedBw: " + getAllocatedBw());
Log.printLine("RequestedBw: " + getRequestedBw());
final HostStateHistoryEntry newState = new HostStateHistoryEntry(time, allocatedMips, requestedMips, getAllocatedIops(), getRequestedIops(), getAllocatedRam(), getRequestedRam(), getAllocatedBw(), getRequestedBw(), active);
if (!stateHistory.isEmpty()) {
final HostStateHistoryEntry previousState = stateHistory.get(stateHistory.size() - 1);
......@@ -1048,13 +1046,6 @@ public class HostSimple implements Host {
@Override
public long getAllocatedRam() {
return allocatedRam;
}
@Override
public long getRequestedRam() {
long requestedRam = 0;
......@@ -1066,11 +1057,6 @@ public class HostSimple implements Host {
return requestedRam;
}
@Override
public long getAllocatedIops() {
return allocatedIops;
}
@Override
public long getRequestedIops() {
long requestedIops = 0;
......@@ -1096,10 +1082,21 @@ public class HostSimple implements Host {
}
@Override
public long getAllocatedBw() {
return bw.getAllocatedResource();
}
@Override
public long getAllocatedIops() {
return iops.getAllocatedResource();
}
@Override
public long getAllocatedBw() {
return allocatedBw;
public long getAllocatedRam() {
return ram.getAllocatedResource();
}
}