package org.cloudbus.cloudsim.container.resourceAllocatorMigrationEnabled; import org.cloudbus.cloudsim.container.resourceAllocators.PowerContainerVmAllocationAbstract; import org.cloudbus.cloudsim.container.vmSelectionPolicies.PowerContainerVmSelectionPolicy; import org.cloudbus.cloudsim.container.core.*; import org.cloudbus.cloudsim.container.lists.PowerContainerVmList; import org.cloudbus.cloudsim.Log; import org.cloudbus.cloudsim.core.CloudSim; import org.cloudbus.cloudsim.util.ExecutionTimeMeasurer; import java.util.*; /** * Created by sareh on 28/07/15. */ public abstract class PowerContainerVmAllocationPolicyMigrationAbstract extends PowerContainerVmAllocationAbstract { /** * The vm selection policy. */ private PowerContainerVmSelectionPolicy vmSelectionPolicy; /** * The saved allocation. */ private final List<Map<String, Object>> savedAllocation = new ArrayList<Map<String, Object>>(); /** * The utilization history. */ private final Map<Integer, List<Double>> utilizationHistory = new HashMap<Integer, List<Double>>(); /** * The metric history. */ private final Map<Integer, List<Double>> metricHistory = new HashMap<Integer, List<Double>>(); /** * The time history. */ private final Map<Integer, List<Double>> timeHistory = new HashMap<Integer, List<Double>>(); /** * The execution time history vm selection. */ private final List<Double> executionTimeHistoryVmSelection = new LinkedList<Double>(); /** * The execution time history host selection. */ private final List<Double> executionTimeHistoryHostSelection = new LinkedList<Double>(); /** * The execution time history vm reallocation. */ private final List<Double> executionTimeHistoryVmReallocation = new LinkedList<Double>(); /** * The execution time history total. */ private final List<Double> executionTimeHistoryTotal = new LinkedList<Double>(); /** * Instantiates a new power vm allocation policy migration abstract. * * @param hostList the host list * @param vmSelectionPolicy the vm selection policy */ public PowerContainerVmAllocationPolicyMigrationAbstract( List<? extends ContainerHost> hostList, PowerContainerVmSelectionPolicy vmSelectionPolicy) { super(hostList); setVmSelectionPolicy(vmSelectionPolicy); } /** * Optimize allocation of the VMs according to current utilization. * * @param vmList the vm list * @return the array list< hash map< string, object>> */ @Override public List<Map<String, Object>> optimizeAllocation(List<? extends ContainerVm> vmList) { ExecutionTimeMeasurer.start("optimizeAllocationTotal"); ExecutionTimeMeasurer.start("optimizeAllocationHostSelection"); List<PowerContainerHostUtilizationHistory> overUtilizedHosts = getOverUtilizedHosts(); getExecutionTimeHistoryHostSelection().add( ExecutionTimeMeasurer.end("optimizeAllocationHostSelection")); printOverUtilizedHosts(overUtilizedHosts); saveAllocation(); ExecutionTimeMeasurer.start("optimizeAllocationVmSelection"); List<? extends ContainerVm> vmsToMigrate = getVmsToMigrateFromHosts(overUtilizedHosts); getExecutionTimeHistoryVmSelection().add(ExecutionTimeMeasurer.end("optimizeAllocationVmSelection")); Log.printLine("Reallocation of VMs from the over-utilized hosts:"); ExecutionTimeMeasurer.start("optimizeAllocationVmReallocation"); List<Map<String, Object>> migrationMap = getNewVmPlacement(vmsToMigrate, new HashSet<ContainerHost>( overUtilizedHosts)); getExecutionTimeHistoryVmReallocation().add( ExecutionTimeMeasurer.end("optimizeAllocationVmReallocation")); Log.printLine(); migrationMap.addAll(getMigrationMapFromUnderUtilizedHosts(overUtilizedHosts, migrationMap)); restoreAllocation(); getExecutionTimeHistoryTotal().add(ExecutionTimeMeasurer.end("optimizeAllocationTotal")); return migrationMap; } /** * Gets the migration map from under utilized hosts. * * @param overUtilizedHosts the over utilized hosts * @return the migration map from under utilized hosts */ protected List<Map<String, Object>> getMigrationMapFromUnderUtilizedHosts( List<PowerContainerHostUtilizationHistory> overUtilizedHosts, List<Map<String, Object>> previouseMap) { List<Map<String, Object>> migrationMap = new LinkedList<Map<String, Object>>(); List<PowerContainerHost> switchedOffHosts = getSwitchedOffHosts(); // over-utilized hosts + hosts that are selected to migrate VMs to from over-utilized hosts Set<PowerContainerHost> excludedHostsForFindingUnderUtilizedHost = new HashSet<>(); excludedHostsForFindingUnderUtilizedHost.addAll(overUtilizedHosts); excludedHostsForFindingUnderUtilizedHost.addAll(switchedOffHosts); excludedHostsForFindingUnderUtilizedHost.addAll(extractHostListFromMigrationMap(previouseMap)); // over-utilized + under-utilized hosts Set<PowerContainerHost> excludedHostsForFindingNewVmPlacement = new HashSet<>(); excludedHostsForFindingNewVmPlacement.addAll(overUtilizedHosts); excludedHostsForFindingNewVmPlacement.addAll(switchedOffHosts); int numberOfHosts = getContainerHostList().size(); while (true) { if (numberOfHosts == excludedHostsForFindingUnderUtilizedHost.size()) { break; } PowerContainerHost underUtilizedHost = getUnderUtilizedHost(excludedHostsForFindingUnderUtilizedHost); if (underUtilizedHost == null) { break; } Log.printConcatLine("Under-utilized host: host #", underUtilizedHost.getId(), "\n"); excludedHostsForFindingUnderUtilizedHost.add(underUtilizedHost); excludedHostsForFindingNewVmPlacement.add(underUtilizedHost); List<? extends ContainerVm> vmsToMigrateFromUnderUtilizedHost = getVmsToMigrateFromUnderUtilizedHost(underUtilizedHost); if (vmsToMigrateFromUnderUtilizedHost.isEmpty()) { continue; } Log.print("Reallocation of VMs from the under-utilized host: "); if (!Log.isDisabled()) { for (ContainerVm vm : vmsToMigrateFromUnderUtilizedHost) { Log.print(vm.getId() + " "); } } Log.printLine(); List<Map<String, Object>> newVmPlacement = getNewVmPlacementFromUnderUtilizedHost( vmsToMigrateFromUnderUtilizedHost, excludedHostsForFindingNewVmPlacement); excludedHostsForFindingUnderUtilizedHost.addAll(extractHostListFromMigrationMap(newVmPlacement)); migrationMap.addAll(newVmPlacement); Log.printLine(); } excludedHostsForFindingUnderUtilizedHost.clear(); excludedHostsForFindingNewVmPlacement.clear(); return migrationMap; } /** * Prints the over utilized hosts. * * @param overUtilizedHosts the over utilized hosts */ protected void printOverUtilizedHosts(List<PowerContainerHostUtilizationHistory> overUtilizedHosts) { if (!Log.isDisabled()) { Log.printLine("Over-utilized hosts:"); for (PowerContainerHostUtilizationHistory host : overUtilizedHosts) { Log.printConcatLine("Host #", host.getId()); } Log.printLine(); } } /** * Find host for vm. * * @param vm the vm * @param excludedHosts the excluded hosts * @return the power host */ public PowerContainerHost findHostForVm(ContainerVm vm, Set<? extends ContainerHost> excludedHosts) { double minPower = Double.MAX_VALUE; PowerContainerHost allocatedHost = null; for (PowerContainerHost host : this.<PowerContainerHost>getContainerHostList()) { if (excludedHosts.contains(host)) { continue; } if (host.isSuitableForContainerVm(vm)) { if (getUtilizationOfCpuMips(host) != 0 && isHostOverUtilizedAfterAllocation(host, vm)) { continue; } try { double powerAfterAllocation = getPowerAfterAllocation(host, vm); if (powerAfterAllocation != -1) { double powerDiff = powerAfterAllocation - host.getPower(); if (powerDiff < minPower) { minPower = powerDiff; allocatedHost = host; } } } catch (Exception e) { } } } return allocatedHost; } /** * Checks if is host over utilized after allocation. * * @param host the host * @param vm the vm * @return true, if is host over utilized after allocation */ protected boolean isHostOverUtilizedAfterAllocation(PowerContainerHost host, ContainerVm vm) { boolean isHostOverUtilizedAfterAllocation = true; if (host.containerVmCreate(vm)) { isHostOverUtilizedAfterAllocation = isHostOverUtilized(host); host.containerVmDestroy(vm); } return isHostOverUtilizedAfterAllocation; } /** * Find host for vm. * * @param vm the vm * @return the power host */ @Override public PowerContainerHost findHostForVm(ContainerVm vm) { Set<ContainerHost> excludedHosts = new HashSet<>(); if (vm.getHost() != null) { excludedHosts.add(vm.getHost()); } PowerContainerHost hostForVm = findHostForVm(vm, excludedHosts); excludedHosts.clear(); return hostForVm; } /** * Extract host list from migration map. * * @param migrationMap the migration map * @return the list */ protected List<PowerContainerHost> extractHostListFromMigrationMap(List<Map<String, Object>> migrationMap) { List<PowerContainerHost> hosts = new LinkedList<PowerContainerHost>(); for (Map<String, Object> map : migrationMap) { hosts.add((PowerContainerHost) map.get("host")); } return hosts; } /** * Gets the new vm placement. * * @param vmsToMigrate the vms to migrate * @param excludedHosts the excluded hosts * @return the new vm placement */ protected List<Map<String, Object>> getNewVmPlacement( List<? extends ContainerVm> vmsToMigrate, Set<? extends ContainerHost> excludedHosts) { List<Map<String, Object>> migrationMap = new LinkedList<Map<String, Object>>(); PowerContainerVmList.sortByCpuUtilization(vmsToMigrate); for (ContainerVm vm : vmsToMigrate) { PowerContainerHost allocatedHost = findHostForVm(vm, excludedHosts); if (allocatedHost != null) { allocatedHost.containerVmCreate(vm); Log.printConcatLine("VM #", vm.getId(), " allocated to host #", allocatedHost.getId()); Map<String, Object> migrate = new HashMap<String, Object>(); migrate.put("vm", vm); migrate.put("host", allocatedHost); migrationMap.add(migrate); } } return migrationMap; } /** * Gets the new vm placement from under utilized host. * * @param vmsToMigrate the vms to migrate * @param excludedHosts the excluded hosts * @return the new vm placement from under utilized host */ protected List<Map<String, Object>> getNewVmPlacementFromUnderUtilizedHost( List<? extends ContainerVm> vmsToMigrate, Set<? extends ContainerHost> excludedHosts) { List<Map<String, Object>> migrationMap = new LinkedList<Map<String, Object>>(); PowerContainerVmList.sortByCpuUtilization(vmsToMigrate); for (ContainerVm vm : vmsToMigrate) { PowerContainerHost allocatedHost = findHostForVm(vm, excludedHosts); if (allocatedHost != null) { allocatedHost.containerVmCreate(vm); Log.printConcatLine("VM #", vm.getId(), " allocated to host #", allocatedHost.getId()); Map<String, Object> migrate = new HashMap<String, Object>(); migrate.put("vm", vm); migrate.put("host", allocatedHost); migrationMap.add(migrate); } else { Log.printLine("Not all VMs can be reallocated from the host, reallocation cancelled"); for (Map<String, Object> map : migrationMap) { ((ContainerHost) map.get("host")).containerVmDestroy((ContainerVm) map.get("vm")); } migrationMap.clear(); break; } } return migrationMap; } /** * Gets the vms to migrate from hosts. * * @param overUtilizedHosts the over utilized hosts * @return the vms to migrate from hosts */ protected List<? extends ContainerVm> getVmsToMigrateFromHosts(List<PowerContainerHostUtilizationHistory> overUtilizedHosts) { List<ContainerVm> vmsToMigrate = new LinkedList<ContainerVm>(); for (PowerContainerHostUtilizationHistory host : overUtilizedHosts) { while (true) { ContainerVm vm = getVmSelectionPolicy().getVmToMigrate(host); if (vm == null) { break; } vmsToMigrate.add(vm); host.containerVmDestroy(vm); if (!isHostOverUtilized(host)) { break; } } } return vmsToMigrate; } /** * Gets the vms to migrate from under utilized host. * * @param host the host * @return the vms to migrate from under utilized host */ protected List<? extends ContainerVm> getVmsToMigrateFromUnderUtilizedHost(PowerContainerHost host) { List<ContainerVm> vmsToMigrate = new LinkedList<ContainerVm>(); for (ContainerVm vm : host.getVmList()) { if (!vm.isInMigration()) { vmsToMigrate.add(vm); } } return vmsToMigrate; } /** * Gets the over utilized hosts. * * @return the over utilized hosts */ protected List<PowerContainerHostUtilizationHistory> getOverUtilizedHosts() { List<PowerContainerHostUtilizationHistory> overUtilizedHosts = new LinkedList<PowerContainerHostUtilizationHistory>(); for (PowerContainerHostUtilizationHistory host : this.<PowerContainerHostUtilizationHistory>getContainerHostList()) { if (isHostOverUtilized(host)) { overUtilizedHosts.add(host); } } return overUtilizedHosts; } /** * Gets the switched off host. * * @return the switched off host */ protected List<PowerContainerHost> getSwitchedOffHosts() { List<PowerContainerHost> switchedOffHosts = new LinkedList<PowerContainerHost>(); for (PowerContainerHost host : this.<PowerContainerHost>getContainerHostList()) { if (host.getUtilizationOfCpu() == 0) { switchedOffHosts.add(host); } } return switchedOffHosts; } /** * Gets the under utilized host. * * @param excludedHosts the excluded hosts * @return the under utilized host */ protected PowerContainerHost getUnderUtilizedHost(Set<? extends ContainerHost> excludedHosts) { double minUtilization = 1; PowerContainerHost underUtilizedHost = null; for (PowerContainerHost host : this.<PowerContainerHost>getContainerHostList()) { if (excludedHosts.contains(host)) { continue; } double utilization = host.getUtilizationOfCpu(); if (utilization > 0 && utilization < minUtilization && !areAllVmsMigratingOutOrAnyVmMigratingIn(host)&& !areAllContainersMigratingOutOrAnyContainersMigratingIn(host)) { minUtilization = utilization; underUtilizedHost = host; } } return underUtilizedHost; } /** * Checks whether all vms are in migration. * * @param host the host * @return true, if successful */ protected boolean areAllVmsMigratingOutOrAnyVmMigratingIn(PowerContainerHost host) { for (PowerContainerVm vm : host.<PowerContainerVm>getVmList()) { if (!vm.isInMigration()) { return false; } if (host.getVmsMigratingIn().contains(vm)) { return true; } } return true; } /** * Checks whether all vms are in migration. * * @param host the host * @return true, if successful */ protected boolean areAllContainersMigratingOutOrAnyContainersMigratingIn(PowerContainerHost host) { for (PowerContainerVm vm : host.<PowerContainerVm>getVmList()) { if(vm.getContainersMigratingIn().size() != 0){ return true; } for(Container container:vm.getContainerList()){ if(!container.isInMigration()){ return false; } } } return true; } /** * Checks if is host over utilized. * * @param host the host * @return true, if is host over utilized */ protected abstract boolean isHostOverUtilized(PowerContainerHost host); /** * Checks if is host over utilized. * * @param host the host * @return true, if is host over utilized */ protected abstract boolean isHostUnderUtilized(PowerContainerHost host); /** * Adds the history value. * * @param host the host * @param metric the metric */ protected void addHistoryEntry(ContainerHostDynamicWorkload host, double metric) { int hostId = host.getId(); if (!getTimeHistory().containsKey(hostId)) { getTimeHistory().put(hostId, new LinkedList<Double>()); } if (!getUtilizationHistory().containsKey(hostId)) { getUtilizationHistory().put(hostId, new LinkedList<Double>()); } if (!getMetricHistory().containsKey(hostId)) { getMetricHistory().put(hostId, new LinkedList<Double>()); } if (!getTimeHistory().get(hostId).contains(CloudSim.clock())) { getTimeHistory().get(hostId).add(CloudSim.clock()); getUtilizationHistory().get(hostId).add(host.getUtilizationOfCpu()); getMetricHistory().get(hostId).add(metric); } } /** * Save allocation. */ protected void saveAllocation() { getSavedAllocation().clear(); for (ContainerHost host : getContainerHostList()) { for (ContainerVm vm : host.getVmList()) { if (host.getVmsMigratingIn().contains(vm)) { continue; } Map<String, Object> map = new HashMap<String, Object>(); map.put("host", host); map.put("vm", vm); getSavedAllocation().add(map); } } } /** * Restore allocation. */ protected void restoreAllocation() { for (ContainerHost host : getContainerHostList()) { host.containerVmDestroyAll(); host.reallocateMigratingInContainerVms(); } for (Map<String, Object> map : getSavedAllocation()) { ContainerVm vm = (ContainerVm) map.get("vm"); PowerContainerHost host = (PowerContainerHost) map.get("host"); if (!host.containerVmCreate(vm)) { Log.printConcatLine("Couldn't restore VM #", vm.getId(), " on host #", host.getId()); System.exit(0); } getVmTable().put(vm.getUid(), host); } } /** * Gets the power after allocation. * * @param host the host * @param vm the vm * @return the power after allocation */ protected double getPowerAfterAllocation(PowerContainerHost host, ContainerVm vm) { double power = 0; try { power = host.getPowerModel().getPower(getMaxUtilizationAfterAllocation(host, vm)); } catch (Exception e) { e.printStackTrace(); System.exit(0); } return power; } /** * Gets the power after allocation. We assume that load is balanced between PEs. The only * restriction is: VM's max MIPS < PE's MIPS * * @param host the host * @param vm the vm * @return the power after allocation */ protected double getMaxUtilizationAfterAllocation(PowerContainerHost host, ContainerVm vm) { double requestedTotalMips = vm.getCurrentRequestedTotalMips(); double hostUtilizationMips = getUtilizationOfCpuMips(host); double hostPotentialUtilizationMips = hostUtilizationMips + requestedTotalMips; double pePotentialUtilization = hostPotentialUtilizationMips / host.getTotalMips(); return pePotentialUtilization; } /** * Gets the utilization of the CPU in MIPS for the current potentially allocated VMs. * * @param host the host * @return the utilization of the CPU in MIPS */ protected double getUtilizationOfCpuMips(PowerContainerHost host) { double hostUtilizationMips = 0; for (ContainerVm vm2 : host.getVmList()) { if (host.getVmsMigratingIn().contains(vm2)) { // calculate additional potential CPU usage of a migrating in VM hostUtilizationMips += host.getTotalAllocatedMipsForContainerVm(vm2) * 0.9 / 0.1; } hostUtilizationMips += host.getTotalAllocatedMipsForContainerVm(vm2); } return hostUtilizationMips; } /** * Gets the saved allocation. * * @return the saved allocation */ protected List<Map<String, Object>> getSavedAllocation() { return savedAllocation; } /** * Sets the vm selection policy. * * @param vmSelectionPolicy the new vm selection policy */ protected void setVmSelectionPolicy(PowerContainerVmSelectionPolicy vmSelectionPolicy) { this.vmSelectionPolicy = vmSelectionPolicy; } /** * Gets the vm selection policy. * * @return the vm selection policy */ protected PowerContainerVmSelectionPolicy getVmSelectionPolicy() { return vmSelectionPolicy; } /** * Gets the utilization history. * * @return the utilization history */ public Map<Integer, List<Double>> getUtilizationHistory() { return utilizationHistory; } /** * Gets the metric history. * * @return the metric history */ public Map<Integer, List<Double>> getMetricHistory() { return metricHistory; } /** * Gets the time history. * * @return the time history */ public Map<Integer, List<Double>> getTimeHistory() { return timeHistory; } /** * Gets the execution time history vm selection. * * @return the execution time history vm selection */ public List<Double> getExecutionTimeHistoryVmSelection() { return executionTimeHistoryVmSelection; } /** * Gets the execution time history host selection. * * @return the execution time history host selection */ public List<Double> getExecutionTimeHistoryHostSelection() { return executionTimeHistoryHostSelection; } /** * Gets the execution time history vm reallocation. * * @return the execution time history vm reallocation */ public List<Double> getExecutionTimeHistoryVmReallocation() { return executionTimeHistoryVmReallocation; } /** * Gets the execution time history total. * * @return the execution time history total */ public List<Double> getExecutionTimeHistoryTotal() { return executionTimeHistoryTotal; } // public abstract List<? extends Container> getContainersToMigrateFromHosts(List<PowerContainerHostUtilizationHistory> overUtilizedHosts); }