/*
* 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;
import java.util.ArrayList;
import java.util.List;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.lists.PeList;
import org.cloudbus.cloudsim.provisioners.BwProvisioner;
import org.cloudbus.cloudsim.provisioners.RamProvisioner;
/**
* A Host is a Physical Machine (PM) inside a Datacenter. It is also called as a Server.
* It executes actions related to management of virtual machines (e.g., creation and destruction).
* A host has a defined policy for provisioning memory and bw, as well as an allocation policy for
* Pe's to virtual machines. A host is associated to a datacenter. It can host virtual machines.
*
* @author Rodrigo N. Calheiros
* @author Anton Beloglazov
* @since CloudSim Toolkit 1.0
*/
public class Host {
/** The id of the host. */
private int id;
/** The storage capacity. */
private long storage;
/** The ram provisioner. */
private RamProvisioner ramProvisioner;
/** The bw provisioner. */
private BwProvisioner bwProvisioner;
/** The allocation policy for scheduling VM execution. */
private VmScheduler vmScheduler;
/** The list of VMs assigned to the host. */
private final List<? extends Vm> vmList = new ArrayList<Vm>();
/** The Processing Elements (PEs) of the host, that
* represent the CPU cores of it, and thus, its processing capacity. */
private List<? extends Pe> peList;
/** Tells whether this host is working properly or has failed. */
private boolean failed;
/** The VMs migrating in. */
private final List<Vm> vmsMigratingIn = new ArrayList<Vm>();
/** The datacenter where the host is placed. */
private Datacenter datacenter;
/**
* Instantiates a new host.
*
* @param id the host id
* @param ramProvisioner the ram provisioner
* @param bwProvisioner the bw provisioner
* @param storage the storage capacity
* @param peList the host's PEs list
* @param vmScheduler the vm scheduler
*/
public Host(
int id,
RamProvisioner ramProvisioner,
BwProvisioner bwProvisioner,
long storage,
List<? extends Pe> peList,
VmScheduler vmScheduler) {
setId(id);
setRamProvisioner(ramProvisioner);
setBwProvisioner(bwProvisioner);
setStorage(storage);
setVmScheduler(vmScheduler);
setPeList(peList);
setFailed(false);
}
/**
* Requests updating of cloudlets' processing in VMs running in this host.
*
* @param currentTime the current time
* @return expected time of completion of the next cloudlet in all VMs in this host or
* {@link Double#MAX_VALUE} if there is no future events expected in this host
* @pre currentTime >= 0.0
* @post $none
* @todo there is an inconsistency between the return value of this method
* and the individual call of {@link Vm#updateVmProcessing(double, java.util.List),
* and consequently the {@link CloudletScheduler#updateVmProcessing(double, java.util.List)}.
* The current method returns {@link Double#MAX_VALUE} while the other ones
* return 0. It has to be checked if there is a reason for this
* difference.}
*/
public double updateVmsProcessing(double currentTime) {
double smallerTime = Double.MAX_VALUE;
for (Vm vm : getVmList()) {
double time = vm.updateVmProcessing(
currentTime, getVmScheduler().getAllocatedMipsForVm(vm));
if (time > 0.0 && time < smallerTime) {
smallerTime = time;
}
}
return smallerTime;
}
/**
* Adds a VM migrating into the current host.
*
* @param vm the vm
*/
public void addMigratingInVm(Vm vm) {
vm.setInMigration(true);
if (!getVmsMigratingIn().contains(vm)) {
if (getStorage() < vm.getSize()) {
Log.printConcatLine("[VmScheduler.addMigratingInVm] Allocation of VM #", vm.getId(), " to Host #",
getId(), " failed by storage");
System.exit(0);
}
if (!getRamProvisioner().allocateRamForVm(vm, vm.getCurrentRequestedRam())) {
Log.printConcatLine("[VmScheduler.addMigratingInVm] Allocation of VM #", vm.getId(), " to Host #",
getId(), " failed by RAM");
System.exit(0);
}
if (!getBwProvisioner().allocateBwForVm(vm, vm.getCurrentRequestedBw())) {
Log.printLine("[VmScheduler.addMigratingInVm] Allocation of VM #" + vm.getId() + " to Host #"
+ getId() + " failed by BW");
System.exit(0);
}
getVmScheduler().getVmsMigratingIn().add(vm.getUid());
if (!getVmScheduler().allocatePesForVm(vm, vm.getCurrentRequestedMips())) {
Log.printLine("[VmScheduler.addMigratingInVm] Allocation of VM #" + vm.getId() + " to Host #"
+ getId() + " failed by MIPS");
System.exit(0);
}
setStorage(getStorage() - vm.getSize());
getVmsMigratingIn().add(vm);
getVmList().add(vm);
updateVmsProcessing(CloudSim.clock());
vm.getHost().updateVmsProcessing(CloudSim.clock());
}
}
/**
* Removes a migrating in vm.
*
* @param vm the vm
*/
public void removeMigratingInVm(Vm vm) {
vmDeallocate(vm);
getVmsMigratingIn().remove(vm);
getVmList().remove(vm);
getVmScheduler().getVmsMigratingIn().remove(vm.getUid());
vm.setInMigration(false);
}
/**
* Reallocate migrating in vms. Gets the VM in the migrating in queue
* and allocate them on the host.
*/
public void reallocateMigratingInVms() {
for (Vm vm : getVmsMigratingIn()) {
if (!getVmList().contains(vm)) {
getVmList().add(vm);
}
if (!getVmScheduler().getVmsMigratingIn().contains(vm.getUid())) {
getVmScheduler().getVmsMigratingIn().add(vm.getUid());
}
getRamProvisioner().allocateRamForVm(vm, vm.getCurrentRequestedRam());
getBwProvisioner().allocateBwForVm(vm, vm.getCurrentRequestedBw());
getVmScheduler().allocatePesForVm(vm, vm.getCurrentRequestedMips());
setStorage(getStorage() - vm.getSize());
}
}
/**
* Checks if the host is suitable for vm. If it has enough resources
* to attend the VM.
*
* @param vm the vm
* @return true, if is suitable for vm
*/
public boolean isSuitableForVm(Vm vm) {
return (getVmScheduler().getPeCapacity() >= vm.getCurrentRequestedMaxMips()
&& getVmScheduler().getAvailableMips() >= vm.getCurrentRequestedTotalMips()
&& getRamProvisioner().isSuitableForVm(vm, vm.getCurrentRequestedRam()) && getBwProvisioner()
.isSuitableForVm(vm, vm.getCurrentRequestedBw()));
}
/**
* Try to allocate resources to a new VM in the Host.
*
* @param vm Vm being started
* @return $true if the VM could be started in the host; $false otherwise
* @pre $none
* @post $none
*/
public boolean vmCreate(Vm vm) {
if (getStorage() < vm.getSize()) {
Log.printConcatLine("[VmScheduler.vmCreate] Allocation of VM #", vm.getId(), " to Host #", getId(),
" failed by storage");
return false;
}
if (!getRamProvisioner().allocateRamForVm(vm, vm.getCurrentRequestedRam())) {
Log.printConcatLine("[VmScheduler.vmCreate] Allocation of VM #", vm.getId(), " to Host #", getId(),
" failed by RAM");
return false;
}
if (!getBwProvisioner().allocateBwForVm(vm, vm.getCurrentRequestedBw())) {
Log.printConcatLine("[VmScheduler.vmCreate] Allocation of VM #", vm.getId(), " to Host #", getId(),
" failed by BW");
getRamProvisioner().deallocateRamForVm(vm);
return false;
}
if (!getVmScheduler().allocatePesForVm(vm, vm.getCurrentRequestedMips())) {
Log.printConcatLine("[VmScheduler.vmCreate] Allocation of VM #", vm.getId(), " to Host #", getId(),
" failed by MIPS");
getRamProvisioner().deallocateRamForVm(vm);
getBwProvisioner().deallocateBwForVm(vm);
return false;
}
setStorage(getStorage() - vm.getSize());
getVmList().add(vm);
vm.setHost(this);
return true;
}
/**
* Destroys a VM running in the host.
*
* @param vm the VM
* @pre $none
* @post $none
*/
public void vmDestroy(Vm vm) {
if (vm != null) {
vmDeallocate(vm);
getVmList().remove(vm);
vm.setHost(null);
}
}
/**
* Destroys all VMs running in the host.
*
* @pre $none
* @post $none
*/
public void vmDestroyAll() {
vmDeallocateAll();
for (Vm vm : getVmList()) {
vm.setHost(null);
setStorage(getStorage() + vm.getSize());
}
getVmList().clear();
}
/**
* Deallocate all resources of a VM.
*
* @param vm the VM
*/
protected void vmDeallocate(Vm vm) {
getRamProvisioner().deallocateRamForVm(vm);
getBwProvisioner().deallocateBwForVm(vm);
getVmScheduler().deallocatePesForVm(vm);
setStorage(getStorage() + vm.getSize());
}
/**
* Deallocate all resources of all VMs.
*/
protected void vmDeallocateAll() {
getRamProvisioner().deallocateRamForAllVms();
getBwProvisioner().deallocateBwForAllVms();
getVmScheduler().deallocatePesForAllVms();
}
/**
* Gets a VM by its id and user.
*
* @param vmId the vm id
* @param userId ID of VM's owner
* @return the virtual machine object, $null if not found
* @pre $none
* @post $none
*/
public Vm getVm(int vmId, int userId) {
for (Vm vm : getVmList()) {
if (vm.getId() == vmId && vm.getUserId() == userId) {
return vm;
}
}
return null;
}
/**
* Gets the pes number.
*
* @return the pes number
*/
public int getNumberOfPes() {
return getPeList().size();
}
/**
* Gets the free pes number.
*
* @return the free pes number
*/
public int getNumberOfFreePes() {
return PeList.getNumberOfFreePes(getPeList());
}
/**
* Gets the total mips.
*
* @return the total mips
*/
public int getTotalMips() {
return PeList.getTotalMips(getPeList());
}
/**
* Allocates PEs for a VM.
*
* @param vm the vm
* @param mipsShare the list of MIPS share to be allocated to the VM
* @return $true if this policy allows a new VM in the host, $false otherwise
* @pre $none
* @post $none
*/
public boolean allocatePesForVm(Vm vm, List<Double> mipsShare) {
return getVmScheduler().allocatePesForVm(vm, mipsShare);
}
/**
* Releases PEs allocated to a VM.
*
* @param vm the vm
* @pre $none
* @post $none
*/
public void deallocatePesForVm(Vm vm) {
getVmScheduler().deallocatePesForVm(vm);
}
/**
* Gets the MIPS share of each Pe that is allocated to a given VM.
*
* @param vm the vm
* @return an array containing the amount of MIPS of each pe that is available to the VM
* @pre $none
* @post $none
*/
public List<Double> getAllocatedMipsForVm(Vm vm) {
return getVmScheduler().getAllocatedMipsForVm(vm);
}
/**
* Gets the total allocated MIPS for a VM along all its PEs.
*
* @param vm the vm
* @return the allocated mips for vm
*/
public double getTotalAllocatedMipsForVm(Vm vm) {
return getVmScheduler().getTotalAllocatedMipsForVm(vm);
}
/**
* Returns the maximum available MIPS among all the PEs of the host.
*
* @return max mips
*/
public double getMaxAvailableMips() {
return getVmScheduler().getMaxAvailableMips();
}
/**
* Gets the total free MIPS available at the host.
*
* @return the free mips
*/
public double getAvailableMips() {
return getVmScheduler().getAvailableMips();
}
/**
* Gets the host bw.
*
* @return the host bw
* @pre $none
* @post $result > 0
*/
public long getBw() {
return getBwProvisioner().getBw();
}
/**
* Gets the host memory.
*
* @return the host memory
* @pre $none
* @post $result > 0
*/
public int getRam() {
return getRamProvisioner().getRam();
}
/**
* Gets the host storage.
*
* @return the host storage
* @pre $none
* @post $result >= 0
*/
public long getStorage() {
return storage;
}
/**
* Gets the host id.
*
* @return the host id
*/
public int getId() {
return id;
}
/**
* Sets the host id.
*
* @param id the new host id
*/
protected void setId(int id) {
this.id = id;
}
/**
* Gets the ram provisioner.
*
* @return the ram provisioner
*/
public RamProvisioner getRamProvisioner() {
return ramProvisioner;
}
/**
* Sets the ram provisioner.
*
* @param ramProvisioner the new ram provisioner
*/
protected void setRamProvisioner(RamProvisioner ramProvisioner) {
this.ramProvisioner = ramProvisioner;
}
/**
* Gets the bw provisioner.
*
* @return the bw provisioner
*/
public BwProvisioner getBwProvisioner() {
return bwProvisioner;
}
/**
* Sets the bw provisioner.
*
* @param bwProvisioner the new bw provisioner
*/
protected void setBwProvisioner(BwProvisioner bwProvisioner) {
this.bwProvisioner = bwProvisioner;
}
/**
* Gets the VM scheduler.
*
* @return the VM scheduler
*/
public VmScheduler getVmScheduler() {
return vmScheduler;
}
/**
* Sets the VM scheduler.
*
* @param vmScheduler the vm scheduler
*/
protected void setVmScheduler(VmScheduler vmScheduler) {
this.vmScheduler = vmScheduler;
}
/**
* Gets the pe list.
*
* @param <T> the generic type
* @return the pe list
*/
@SuppressWarnings("unchecked")
public <T extends Pe> List<T> getPeList() {
return (List<T>) peList;
}
/**
* Sets the pe list.
*
* @param <T> the generic type
* @param peList the new pe list
*/
protected <T extends Pe> void setPeList(List<T> peList) {
this.peList = peList;
}
/**
* Gets the vm list.
*
* @param <T> the generic type
* @return the vm list
*/
@SuppressWarnings("unchecked")
public <T extends Vm> List<T> getVmList() {
return (List<T>) vmList;
}
/**
* Sets the storage.
*
* @param storage the new storage
*/
protected void setStorage(long storage) {
this.storage = storage;
}
/**
* Checks if the host PEs have failed.
*
* @return true, if the host PEs have failed; false otherwise
*/
public boolean isFailed() {
return failed;
}
/**
* Sets the PEs of the host to a FAILED status. NOTE: <tt>resName</tt> is used for debugging
* purposes, which is <b>ON</b> by default. Use {@link #setFailed(boolean)} if you do not want
* this information.
*
* @param resName the name of the resource
* @param failed the failed
* @return <tt>true</tt> if successful, <tt>false</tt> otherwise
*/
public boolean setFailed(String resName, boolean failed) {
// all the PEs are failed (or recovered, depending on fail)
this.failed = failed;
PeList.setStatusFailed(getPeList(), resName, getId(), failed);
return true;
}
/**
* Sets the PEs of the host to a FAILED status.
*
* @param failed the failed
* @return <tt>true</tt> if successful, <tt>false</tt> otherwise
*/
public boolean setFailed(boolean failed) {
// all the PEs are failed (or recovered, depending on fail)
this.failed = failed;
PeList.setStatusFailed(getPeList(), failed);
return true;
}
/**
* Sets the particular Pe status on the host.
*
* @param peId the pe id
* @param status Pe status, either <tt>Pe.FREE</tt> or <tt>Pe.BUSY</tt>
* @return <tt>true</tt> if the Pe status has changed, <tt>false</tt> otherwise (Pe id might not
* be exist)
* @pre peID >= 0
* @post $none
*/
public boolean setPeStatus(int peId, int status) {
return PeList.setPeStatus(getPeList(), peId, status);
}
/**
* Gets the vms migrating in.
*
* @return the vms migrating in
*/
public List<Vm> getVmsMigratingIn() {
return vmsMigratingIn;
}
/**
* Gets the data center of the host.
*
* @return the data center where the host runs
*/
public Datacenter getDatacenter() {
return datacenter;
}
/**
* Sets the data center of the host.
*
* @param datacenter the data center from this host
*/
public void setDatacenter(Datacenter datacenter) {
this.datacenter = datacenter;
}
}