/*
* Title: CloudSim Toolkit
* Description: CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2009-2012, The University of Melbourne, Australia
*/
package org.cloudbus.cloudsim.power;
import java.util.List;
import java.util.Map;
import org.cloudbus.cloudsim.Datacenter;
import org.cloudbus.cloudsim.DatacenterCharacteristics;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.Storage;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.VmAllocationPolicy;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.core.CloudSimTags;
import org.cloudbus.cloudsim.core.SimEvent;
import org.cloudbus.cloudsim.core.predicates.PredicateType;
/**
* PowerDatacenter is a class that enables simulation of power-aware data centers.
*
* If you are using any algorithms, policies or workload included in the power package please cite
* the following paper:
*
* Anton Beloglazov, and Rajkumar Buyya, "Optimal Online Deterministic Algorithms and Adaptive
* Heuristics for Energy and Performance Efficient Dynamic Consolidation of Virtual Machines in
* Cloud Data Centers", Concurrency and Computation: Practice and Experience (CCPE), Volume 24,
* Issue 13, Pages: 1397-1420, John Wiley & Sons, Ltd, New York, USA, 2012
*
* @author Anton Beloglazov
* @since CloudSim Toolkit 2.0
*/
public class PowerDatacenter extends Datacenter {
/** The power. */
private double power;
/** The disable migrations. */
private boolean disableMigrations;
/** The cloudlet submited. */
private double cloudletSubmitted;
/** The migration count. */
private int migrationCount;
/**
* Instantiates a new datacenter.
*
* @param name the name
* @param characteristics the res config
* @param schedulingInterval the scheduling interval
* @param utilizationBound the utilization bound
* @param vmAllocationPolicy the vm provisioner
* @param storageList the storage list
* @throws Exception the exception
*/
public PowerDatacenter(
String name,
DatacenterCharacteristics characteristics,
VmAllocationPolicy vmAllocationPolicy,
List<Storage> storageList,
double schedulingInterval) throws Exception {
super(name, characteristics, vmAllocationPolicy, storageList, schedulingInterval);
setPower(0.0);
setDisableMigrations(false);
setCloudletSubmitted(-1);
setMigrationCount(0);
}
/**
* Updates processing of each cloudlet running in this PowerDatacenter. It is necessary because
* Hosts and VirtualMachines are simple objects, not entities. So, they don't receive events and
* updating cloudlets inside them must be called from the outside.
*
* @pre $none
* @post $none
*/
@Override
protected void updateCloudletProcessing() {
if (getCloudletSubmitted() == -1 || getCloudletSubmitted() == CloudSim.clock()) {
CloudSim.cancelAll(getId(), new PredicateType(CloudSimTags.VM_DATACENTER_EVENT));
schedule(getId(), getSchedulingInterval(), CloudSimTags.VM_DATACENTER_EVENT);
return;
}
double currentTime = CloudSim.clock();
// if some time passed since last processing
if (currentTime > getLastProcessTime()) {
System.out.print(currentTime + " ");
double minTime = updateCloudetProcessingWithoutSchedulingFutureEventsForce();
if (!isDisableMigrations()) {
List<Map<String, Object>> migrationMap = getVmAllocationPolicy().optimizeAllocation(
getVmList());
if (migrationMap != null) {
for (Map<String, Object> migrate : migrationMap) {
Vm vm = (Vm) migrate.get("vm");
PowerHost targetHost = (PowerHost) migrate.get("host");
PowerHost oldHost = (PowerHost) vm.getHost();
if (oldHost == null) {
Log.formatLine(
"%.2f: Migration of VM #%d to Host #%d is started",
currentTime,
vm.getId(),
targetHost.getId());
} else {
Log.formatLine(
"%.2f: Migration of VM #%d from Host #%d to Host #%d is started",
currentTime,
vm.getId(),
oldHost.getId(),
targetHost.getId());
}
targetHost.addMigratingInVm(vm);
incrementMigrationCount();
/** VM migration delay = RAM / bandwidth **/
// we use BW / 2 to model BW available for migration purposes, the other
// half of BW is for VM communication
// around 16 seconds for 1024 MB using 1 Gbit/s network
send(
getId(),
vm.getRam() / ((double) targetHost.getBw() / (2 * 8000)),
CloudSimTags.VM_MIGRATE,
migrate);
}
}
}
// schedules an event to the next time
if (minTime != Double.MAX_VALUE) {
CloudSim.cancelAll(getId(), new PredicateType(CloudSimTags.VM_DATACENTER_EVENT));
send(getId(), getSchedulingInterval(), CloudSimTags.VM_DATACENTER_EVENT);
}
setLastProcessTime(currentTime);
}
}
/**
* Update cloudet processing without scheduling future events.
*
* @return the double
*/
protected double updateCloudetProcessingWithoutSchedulingFutureEvents() {
if (CloudSim.clock() > getLastProcessTime()) {
return updateCloudetProcessingWithoutSchedulingFutureEventsForce();
}
return 0;
}
/**
* Update cloudet processing without scheduling future events.
*
* @return the double
*/
protected double updateCloudetProcessingWithoutSchedulingFutureEventsForce() {
double currentTime = CloudSim.clock();
double minTime = Double.MAX_VALUE;
double timeDiff = currentTime - getLastProcessTime();
double timeFrameDatacenterEnergy = 0.0;
Log.printLine("\n\n--------------------------------------------------------------\n\n");
Log.formatLine("New resource usage for the time frame starting at %.2f:", currentTime);
for (PowerHost host : this.<PowerHost> getHostList()) {
Log.printLine();
double time = host.updateVmsProcessing(currentTime); // inform VMs to update processing
if (time < minTime) {
minTime = time;
}
Log.formatLine(
"%.2f: [Host #%d] utilization is %.2f%%",
currentTime,
host.getId(),
host.getUtilizationOfCpu() * 100);
}
if (timeDiff > 0) {
Log.formatLine(
"\nEnergy consumption for the last time frame from %.2f to %.2f:",
getLastProcessTime(),
currentTime);
for (PowerHost host : this.<PowerHost> getHostList()) {
double previousUtilizationOfCpu = host.getPreviousUtilizationOfCpu();
double utilizationOfCpu = host.getUtilizationOfCpu();
double timeFrameHostEnergy = host.getEnergyLinearInterpolation(
previousUtilizationOfCpu,
utilizationOfCpu,
timeDiff);
timeFrameDatacenterEnergy += timeFrameHostEnergy;
Log.printLine();
Log.formatLine(
"%.2f: [Host #%d] utilization at %.2f was %.2f%%, now is %.2f%%",
currentTime,
host.getId(),
getLastProcessTime(),
previousUtilizationOfCpu * 100,
utilizationOfCpu * 100);
Log.formatLine(
"%.2f: [Host #%d] energy is %.2f W*sec",
currentTime,
host.getId(),
timeFrameHostEnergy);
}
Log.formatLine(
"\n%.2f: Data center's energy is %.2f W*sec\n",
currentTime,
timeFrameDatacenterEnergy);
}
setPower(getPower() + timeFrameDatacenterEnergy);
checkCloudletCompletion();
/** Remove completed VMs **/
for (PowerHost host : this.<PowerHost> getHostList()) {
for (Vm vm : host.getCompletedVms()) {
getVmAllocationPolicy().deallocateHostForVm(vm);
getVmList().remove(vm);
Log.printLine("VM #" + vm.getId() + " has been deallocated from host #" + host.getId());
}
}
Log.printLine();
setLastProcessTime(currentTime);
return minTime;
}
/*
* (non-Javadoc)
* @see org.cloudbus.cloudsim.Datacenter#processVmMigrate(org.cloudbus.cloudsim.core.SimEvent,
* boolean)
*/
@Override
protected void processVmMigrate(SimEvent ev, boolean ack) {
updateCloudetProcessingWithoutSchedulingFutureEvents();
super.processVmMigrate(ev, ack);
SimEvent event = CloudSim.findFirstDeferred(getId(), new PredicateType(CloudSimTags.VM_MIGRATE));
if (event == null || event.eventTime() > CloudSim.clock()) {
updateCloudetProcessingWithoutSchedulingFutureEventsForce();
}
}
/*
* (non-Javadoc)
* @see cloudsim.Datacenter#processCloudletSubmit(cloudsim.core.SimEvent, boolean)
*/
@Override
protected void processCloudletSubmit(SimEvent ev, boolean ack) {
super.processCloudletSubmit(ev, ack);
setCloudletSubmitted(CloudSim.clock());
}
/**
* Gets the power.
*
* @return the power
*/
public double getPower() {
return power;
}
/**
* Sets the power.
*
* @param power the new power
*/
protected void setPower(double power) {
this.power = power;
}
/**
* Checks if PowerDatacenter is in migration.
*
* @return true, if PowerDatacenter is in migration
*/
protected boolean isInMigration() {
boolean result = false;
for (Vm vm : getVmList()) {
if (vm.isInMigration()) {
result = true;
break;
}
}
return result;
}
/**
* Checks if is disable migrations.
*
* @return true, if is disable migrations
*/
public boolean isDisableMigrations() {
return disableMigrations;
}
/**
* Sets the disable migrations.
*
* @param disableMigrations the new disable migrations
*/
public void setDisableMigrations(boolean disableMigrations) {
this.disableMigrations = disableMigrations;
}
/**
* Checks if is cloudlet submited.
*
* @return true, if is cloudlet submited
*/
protected double getCloudletSubmitted() {
return cloudletSubmitted;
}
/**
* Sets the cloudlet submited.
*
* @param cloudletSubmitted the new cloudlet submited
*/
protected void setCloudletSubmitted(double cloudletSubmitted) {
this.cloudletSubmitted = cloudletSubmitted;
}
/**
* Gets the migration count.
*
* @return the migration count
*/
public int getMigrationCount() {
return migrationCount;
}
/**
* Sets the migration count.
*
* @param migrationCount the new migration count
*/
protected void setMigrationCount(int migrationCount) {
this.migrationCount = migrationCount;
}
/**
* Increment migration count.
*/
protected void incrementMigrationCount() {
setMigrationCount(getMigrationCount() + 1);
}
}