diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..882bac073 --- /dev/null +++ b/.gitignore @@ -0,0 +1,139 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +$Stat* + +# User-specific stuff: +.idea/ +.idea/**/workspace.xml +.idea/**/tasks.xml + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Java template +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +### Eclipse template + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ +### JDeveloper template +# default application storage directory used by the IDE Performance Cache feature +.data/ + +# used for ADF styles caching +temp/ + +# default output directories +classes/ +deploy/ +javadoc/ +target/ + +# lock file, a part of Oracle Credential Store Framework +cwallet.sso.lck +*.iml +/Results/ +Results/ diff --git a/Auction-vs-Balanced.xlsx b/Auction-vs-Balanced.xlsx new file mode 100644 index 000000000..37340bd74 Binary files /dev/null and b/Auction-vs-Balanced.xlsx differ diff --git a/Stat Collection.xlsx b/Stat Collection.xlsx new file mode 100644 index 000000000..f2ff21f63 Binary files /dev/null and b/Stat Collection.xlsx differ diff --git a/Stats-Results1.xlsx b/Stats-Results1.xlsx new file mode 100644 index 000000000..1669ade47 Binary files /dev/null and b/Stats-Results1.xlsx differ diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ConstantsExamples.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ConstantsExamples.java index 0240c8078..c1e8ca63b 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ConstantsExamples.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ConstantsExamples.java @@ -17,7 +17,7 @@ public class ConstantsExamples { public static final boolean ENABLE_OUTPUT = true; public static final boolean OUTPUT_CSV = false; public static final double SCHEDULING_INTERVAL = 300.0D; - public static final double SIMULATION_LIMIT = 87400.0D; + public static final double SIMULATION_LIMIT = 86400.0D; /** * Cloudlet specs */ @@ -71,10 +71,12 @@ public class ConstantsExamples { * population. */ + public static final int NUMBER_HOSTS = 2; + public static final int NUMBER_VMS = 5; + public static final int NUMBER_CLOUDLETS = 2; - public static final int NUMBER_HOSTS = 20; - public static final int NUMBER_VMS = 25; - public static final int NUMBER_CLOUDLETS = 50; +// public static final String CONTAINER_VM_TYPE = "PowerContainerVm"; + public static final String CONTAINER_VM_TYPE = "BidderContainerVM"; //-----------------------The Addresses diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerCloudSimExample1.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerCloudSimExample1.java index 4a0739c7a..6321ae4e7 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerCloudSimExample1.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerCloudSimExample1.java @@ -155,7 +155,8 @@ public static void main(String[] args) { /** * 9- Creating the cloudlet, container and VM lists for submitting to the broker. */ - cloudletList = createContainerCloudletList(brokerId, ConstantsExamples.NUMBER_CLOUDLETS); +// cloudletList = createContainerCloudletList(brokerId, ConstantsExamples.NUMBER_CLOUDLETS); + cloudletList = HelperEx.createContainerCloudletList(brokerId, ContainerCloudSimExample1.class.getClassLoader().getResource("workload/planetlab").getPath(), ConstantsExamples.NUMBER_CLOUDLETS); containerList = createContainerList(brokerId, ConstantsExamples.NUMBER_CLOUDLETS); vmList = createVmList(brokerId, ConstantsExamples.NUMBER_VMS); /** @@ -193,7 +194,8 @@ public static void main(String[] args) { * 15- Printing the results when the simulation is finished. */ List newList = broker.getCloudletReceivedList(); - printCloudletList(newList); +// List newList = broker.getCloudletList(); + HelperEx.printCloudletList(newList); Log.printLine("ContainerCloudSimExample1 finished!"); } catch (Exception e) { @@ -244,41 +246,6 @@ private static ContainerDatacenterBroker createBroker(int overBookingFactor) { return broker; } - /** - * Prints the Cloudlet objects. - * - * @param list list of Cloudlets - */ - private static void printCloudletList(List list) { - int size = list.size(); - Cloudlet cloudlet; - - String indent = " "; - Log.printLine(); - Log.printLine("========== OUTPUT =========="); - Log.printLine("Cloudlet ID" + indent + "STATUS" + indent - + "Data center ID" + indent + "VM ID" + indent + "Time" + indent - + "Start Time" + indent + "Finish Time"); - - DecimalFormat dft = new DecimalFormat("###.##"); - for (int i = 0; i < size; i++) { - cloudlet = list.get(i); - Log.print(indent + cloudlet.getCloudletId() + indent + indent); - - if (cloudlet.getCloudletStatusString() == "Success") { - Log.print("SUCCESS"); - - Log.printLine(indent + indent + cloudlet.getResourceId() - + indent + indent + indent + cloudlet.getVmId() - + indent + indent - + dft.format(cloudlet.getActualCPUTime()) + indent - + indent + dft.format(cloudlet.getExecStartTime()) - + indent + indent - + dft.format(cloudlet.getFinishTime())); - } - } - } - /** * Create the Virtual machines and add them to the list * diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerInitialPlacementTest.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerInitialPlacementTest.java index 2a78612ed..478d8cdcf 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerInitialPlacementTest.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerInitialPlacementTest.java @@ -2,6 +2,7 @@ import java.io.IOException; +import java.nio.file.Paths; /** * This Example is following the format for {@link org.cloudbus.cloudsim.examples.power.planetlab.Dvfs} @@ -35,7 +36,7 @@ public static void main(String[] args) throws IOException { /** * The output folder for the logs. The log files would be located in this folder. */ - String outputFolder = "~/Results"; + String outputFolder = Paths.get(".").toAbsolutePath().normalize().toString() + "/Results"; /** * The allocation policy for VMs. */ diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerOverbooking.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerOverbooking.java index 1602f73ff..3492c93fb 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerOverbooking.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerOverbooking.java @@ -1,7 +1,12 @@ package org.cloudbus.cloudsim.examples.container; +import org.apache.commons.cli.*; +import org.cloudbus.cloudsim.Log; + import java.io.IOException; +import java.util.Optional; +import java.nio.file.Paths; /** * This Example is following the format for {@link org.cloudbus.cloudsim.examples.power.planetlab.Dvfs} @@ -10,6 +15,148 @@ * @author Sareh Fotuhi Piraghaj */ public class ContainerOverbooking { + private Options options = null; + private String[] args = null; + private RunConfig rc = new RunConfig(); + + public RunConfig getRunConfig() { + return rc; + } + + public void setRc(RunConfig rc) { + this.rc = rc; + } + + public void setArgs(String[] args) { + this.args = args; + } + + + /** + * The allocation policy used for allocating containers to VMs. + */ +// String containerAllocationPolicy = "MostFull"; +// String containerAllocationPolicy= "FirstFit"; +// String containerAllocationPolicy= "LeastFull"; +// String containerAllocationPolicy= "Simple"; +// String containerAllocationPolicy = "RandomSelection"; +// String containerAllocationPolicy = "Balanced"; +// String containerAllocationPolicy = "LeastRequested"; +// private String containerAllocationPolicy = "Auction"; + + private void help() { + // This prints out some help + HelpFormatter formater = new HelpFormatter(); + + formater.printHelp("Main", options); + System.exit(0); + } + + private void parse() { + CommandLineParser parser = new DefaultParser(); + CommandLine cmd = null; + RunConfig rc = this.getRunConfig(); + + try { + cmd = parser.parse(options, this.args); + + if (cmd.hasOption("h")) + help(); + + if (cmd.hasOption("runtime")) { + this.rc.setRunTime(Integer.parseInt(cmd.getOptionValue("runtime"))); + // Whatever you want to do with the setting goes here + } + if (cmd.hasOption("i")) { + this.rc.setRepeat(Integer.parseInt(cmd.getOptionValue("i")));; + // Whatever you want to do with the setting goes here + } + if (cmd.hasOption("container")) { + this.rc.setContainerType(cmd.getOptionValue("container")); + // Whatever you want to do with the setting goes here + } + if (cmd.hasOption("s")) { + this.rc.setNumberHosts(Integer.parseInt(cmd.getOptionValue("s"))); + // Whatever you want to do with the setting goes here + } + if (cmd.hasOption("vms")) { + this.rc.setNumberVms(Integer.parseInt(cmd.getOptionValue("vms"))); + // Whatever you want to do with the setting goes here + } + if (cmd.hasOption("c")) { + this.rc.setNumberCloudlets(Integer.parseInt(cmd.getOptionValue("c"))); + // Whatever you want to do with the setting goes here + } + if (cmd.hasOption("cap")) { + this.rc.setContainerAllocationPolicy(cmd.getOptionValue("cap")); + // Whatever you want to do with the setting goes here + } + + } catch (ParseException e) { + Log.printLine("Failed to parse comand line properties " + e); + help(); + } +// System.out.println(rc); + Log.printLine("Configuration: " + rc); + } + + /* + * + */ + private void buildOptions() { + + options = new Options(); + + options.addOption(Option.builder("r") + .longOpt("runtime") + .required(false) + .hasArg() + .type(Number.class) + .desc("run Time") + .build()); + options.addOption(Option.builder("i") + .longOpt("iteration") + .required(false) + .hasArg() + .type(Number.class) + .desc("iterations") + .build()); + options.addOption(Option.builder("c") + .longOpt("container") + .required(false) + .hasArg() + .desc("Type of Container") + .build()); + options.addOption(Option.builder("s") + .longOpt("hosts") + .required(false) + .hasArg() + .type(Number.class) + .desc("Number of Hosts") + .build()); + options.addOption(Option.builder("v") + .longOpt("vms") + .required(false) + .hasArg() + .type(Number.class) + .desc("Number of VMs") + .build()); + options.addOption(Option.builder("c") + .longOpt("cloudlets") + .required(false) + .hasArg() + .type(Number.class) + .desc("Number of Cloudlets") + .build()); + options.addOption(Option.builder("p") + .longOpt("cap") + .required(false) + .hasArg() + .desc("Container Allocation Policy") + .build()); + + + } /** * The main method. @@ -18,62 +165,38 @@ public class ContainerOverbooking { * @throws IOException Signals that an I/O exception has occurred. */ public static void main(String[] args) throws IOException { + // create Options object + + ContainerOverbooking co = new ContainerOverbooking(); + co.setArgs(args); + /** * The experiments can be repeated for (repeat - runtime +1) times. * Please set these values as the arguments of the main function or set them bellow: */ - int runTime = Integer.parseInt(args[0]); - int repeat = Integer.parseInt(args[1]); - for (int i = 10; i < repeat; i += 10) { - boolean enableOutput = true; - boolean outputToFile = true; - /** - * Getting the path of the planet lab workload that is included in the cloudSim Package - */ - String inputFolder = ContainerOverbooking.class.getClassLoader().getResource("workload/planetlab").getPath(); - /** - * The output folder for the logs. The log files would be located in this folder. - */ - String outputFolder = "/Results"; - /** - * The allocation policy for VMs. It has the under utilization and over utilization thresholds used for - * determining the underloaded and oberloaded hosts. - */ - String vmAllocationPolicy = "MSThreshold-Under_0.80_0.70"; // DVFS policy without VM migrations - /** - * The selection policy for containers where a container migration is triggered. - */ - String containerSelectionPolicy = "Cor"; - /** - * The allocation policy used for allocating containers to VMs. - */ - String containerAllocationPolicy = "MostFull"; -// String containerAllocationPolicy= "FirstFit"; -// String containerAllocationPolicy= "LeastFull"; -// String containerAllocationPolicy= "Simple"; -// String containerAllocationPolicy = "Random"; - - /** - * The host selection policy determines which hosts should be selected as the migration destination. - */ - String hostSelectionPolicy = "FirstFit"; - /** - * The VM Selection Policy is used for selecting VMs to migrate when a host status is determined as - * "Overloaded" - */ - String vmSelectionPolicy = "VmMaxC"; - - new RunnerInitiator( - enableOutput, - outputToFile, - inputFolder, - outputFolder, - vmAllocationPolicy, - containerAllocationPolicy, - vmSelectionPolicy, - containerSelectionPolicy, - hostSelectionPolicy, - i, Integer.toString(runTime), outputFolder); + co.buildOptions(); + co.parse(); + RunConfig rc = co.getRunConfig(); + rc.setInputFolder(ContainerOverbooking.class.getClassLoader().getResource("workload/planetlab").getPath()); + rc.setOutputFolder(Paths.get(".").toAbsolutePath().normalize().toString() + "/Results"); + + for (int i = 10; i < rc.getRepeat(); i += 10) { +// RunnerInitiator ri = new RunnerInitiator(rc, i); + RunnerInitiator ri = new RunnerInitiator(); + ri.setRc(rc); + ri.initializeAndStart(i); + +// new RunnerInitiator( +// enableOutput, +// outputToFile, +// inputFolder, +// outputFolder, +// vmAllocationPolicy, +// co.getContainerAllocationPolicy(), +// vmSelectionPolicy, +// containerSelectionPolicy, +// hostSelectionPolicy, +// i, Integer.toString(co.getRunTime()), outputFolder); } } diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerSelectionTest.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerSelectionTest.java index be9e636f8..050c3404f 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerSelectionTest.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/ContainerSelectionTest.java @@ -2,6 +2,8 @@ import java.io.IOException; +import java.nio.file.Paths; + /** * This Example is following the format for {@link org.cloudbus.cloudsim.examples.power.planetlab.Dvfs} * It specifically studies the placement of containers. @@ -22,8 +24,12 @@ public static void main(String[] args) throws IOException { * The experiments can be repeated for (repeat - runtime +1) times. * Please set these values as the arguments of the main function or set them bellow: */ - int runTime = Integer.parseInt(args[0]); - int repeat = Integer.parseInt(args[1]); + int runTime = 2; + int repeat = 2; + if (args.length > 2) { + runTime = Integer.parseInt(args[0]); + repeat = Integer.parseInt(args[1]); + } for (int i = runTime ; i < repeat; ++i) { boolean enableOutput = true; boolean outputToFile = true; @@ -34,7 +40,7 @@ public static void main(String[] args) throws IOException { /** * The output folder for the logs. The log files would be located in this folder. */ - String outputFolder = "~/Results"; + String outputFolder = Paths.get(".").toAbsolutePath().normalize().toString() + "/Results"; /** * The allocation policy for VMs. */ @@ -68,6 +74,7 @@ public static void main(String[] args) throws IOException { int OverBookingFactor = 80; new RunnerInitiator( + enableOutput, outputToFile, inputFolder, diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/HelperEx.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/HelperEx.java index 66f3c5a10..ffb9d58bd 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/HelperEx.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/HelperEx.java @@ -2,10 +2,7 @@ import com.opencsv.CSVWriter; import org.cloudbus.cloudsim.*; -import org.cloudbus.cloudsim.container.containerProvisioners.ContainerBwProvisionerSimple; -import org.cloudbus.cloudsim.container.containerProvisioners.ContainerPe; -import org.cloudbus.cloudsim.container.containerProvisioners.ContainerRamProvisionerSimple; -import org.cloudbus.cloudsim.container.containerProvisioners.CotainerPeProvisionerSimple; +import org.cloudbus.cloudsim.container.containerProvisioners.*; import org.cloudbus.cloudsim.container.containerVmProvisioners.ContainerVmBwProvisionerSimple; import org.cloudbus.cloudsim.container.containerVmProvisioners.ContainerVmPe; import org.cloudbus.cloudsim.container.containerVmProvisioners.ContainerVmPeProvisionerSimple; @@ -15,13 +12,17 @@ import org.cloudbus.cloudsim.container.resourceAllocators.ContainerAllocationPolicy; import org.cloudbus.cloudsim.container.resourceAllocators.ContainerVmAllocationPolicy; import org.cloudbus.cloudsim.container.schedulers.ContainerCloudletSchedulerDynamicWorkload; +import org.cloudbus.cloudsim.container.schedulers.ContainerScheduler; import org.cloudbus.cloudsim.container.schedulers.ContainerSchedulerTimeSharedOverSubscription; import org.cloudbus.cloudsim.container.schedulers.ContainerVmSchedulerTimeSharedOverSubscription; import org.cloudbus.cloudsim.container.utils.IDs; import org.cloudbus.cloudsim.util.MathUtil; +import org.cloudbus.cloudsim.auction.bidder.BidderDatacenterBroker; +import org.cloudbus.cloudsim.auction.bidder.BidderContainerVM; import java.io.*; import java.io.File; +import java.text.DecimalFormat; import java.util.*; /** @@ -36,7 +37,15 @@ public HelperEx() { } - + /** + * Creating the cloudlet list that are going to run on containers + * + * @param brokerId + * @param numberOfCloudlets + * @param inputFolderName + * @return + * @throws FileNotFoundException + */ public static List createContainerCloudletList(int brokerId, String inputFolderName, int numberOfCloudlets) throws FileNotFoundException { ArrayList cloudletList = new ArrayList(); @@ -44,19 +53,30 @@ public static List createContainerCloudletList(int brokerId, long outputSize = 300L; UtilizationModelNull utilizationModelNull = new UtilizationModelNull(); File inputFolder1 = new File(inputFolderName); - File[] files1 = inputFolder1.listFiles(); + File[] directories = inputFolder1.listFiles(); int createdCloudlets = 0; - for (File aFiles1 : files1) { - File inputFolder = new File(aFiles1.toString()); + for (File directory : directories) { + if (!directory.isDirectory()) // Make sure to check it's a directory. + continue; + File inputFolder = new File(directory.toString()); File[] files = inputFolder.listFiles(); for (int i = 0; i < files.length; ++i) { if (createdCloudlets < numberOfCloudlets) { ContainerCloudlet cloudlet = null; try { - cloudlet = new ContainerCloudlet(IDs.pollId(ContainerCloudlet.class), 216000000L * 1000, 1, fileSize, outputSize, + cloudlet = new ContainerCloudlet(IDs.pollId(ContainerCloudlet.class), ConstantsExamples.CLOUDLET_LENGTH, 1, + fileSize, outputSize, new UtilizationModelPlanetLabInMemoryExtended(files[i].getAbsolutePath(), 300.0D), utilizationModelNull, utilizationModelNull); + + // QUESTION: Is this cloudlenght so high because of overbooking???? + +// cloudlet = new ContainerCloudlet(IDs.pollId(ContainerCloudlet.class), 216000000L * 1000, 1, +// fileSize, outputSize, +// new UtilizationModelPlanetLabInMemoryExtended(files[i].getAbsolutePath(), 300.0D), +// utilizationModelNull, utilizationModelNull); + } catch (Exception var13) { var13.printStackTrace(); System.exit(0); @@ -95,7 +115,7 @@ public static List createContainerList(int brokerId, int containersNu } // create the containers for hosting the cloudlets and binding them together. - public static List createVmList(int brokerId, int containerVmsNumber) { + public static List createVmList(int brokerId, int containerVmsNumber, String containerType) { ArrayList containerVms = new ArrayList(); for (int i = 0; i < containerVmsNumber; ++i) { @@ -110,10 +130,31 @@ public static List createVmList(int brokerId, int containerVmsNumbe for (int j = 0; j < ConstantsExamples.VM_PES[vmType]; ++j) { peList.add(new ContainerPe(j, new CotainerPeProvisionerSimple((double) ConstantsExamples.VM_MIPS[vmType]))); } - containerVms.add(new PowerContainerVm(IDs.pollId(ContainerVm.class), brokerId, (double) ConstantsExamples.VM_MIPS[vmType], (float) ConstantsExamples.VM_RAM[vmType], - ConstantsExamples.VM_BW, ConstantsExamples.VM_SIZE, "Xen", new ContainerSchedulerTimeSharedOverSubscription(peList), - new ContainerRamProvisionerSimple(ConstantsExamples.VM_RAM[vmType]), - new ContainerBwProvisionerSimple(ConstantsExamples.VM_BW), peList, ConstantsExamples.SCHEDULING_INTERVAL)); + ContainerVm cVM = null; + switch (containerType) { + case "PowerContainerVm" : + cVM = new PowerContainerVm(IDs.pollId(ContainerVm.class), + brokerId, (double) ConstantsExamples.VM_MIPS[vmType], (float) ConstantsExamples.VM_RAM[vmType], + ConstantsExamples.VM_BW, ConstantsExamples.VM_SIZE, "Xen", + new ContainerSchedulerTimeSharedOverSubscription(peList), + new ContainerRamProvisionerSimple(ConstantsExamples.VM_RAM[vmType]), + new ContainerBwProvisionerSimple(ConstantsExamples.VM_BW), peList, + ConstantsExamples.SCHEDULING_INTERVAL); + + break; + case "BidderContainerVM" : + cVM = new BidderContainerVM(IDs.pollId(ContainerVm.class), + brokerId, (double) ConstantsExamples.VM_MIPS[vmType], (float) ConstantsExamples.VM_RAM[vmType], + ConstantsExamples.VM_BW, ConstantsExamples.VM_SIZE, "Xen", + new ContainerSchedulerTimeSharedOverSubscription(peList), + new ContainerRamProvisionerSimple(ConstantsExamples.VM_RAM[vmType]), + new ContainerBwProvisionerSimple(ConstantsExamples.VM_BW), peList, + ConstantsExamples.SCHEDULING_INTERVAL); + + + break; + } + containerVms.add(cVM); } @@ -160,6 +201,20 @@ public static ContainerDatacenterBroker createBroker(double overBookingFactor) { return broker; } + public static BidderDatacenterBroker createAuctionBroker(double overBookingFactor) { + BidderDatacenterBroker broker = null; + + try { + broker = new BidderDatacenterBroker("Broker"); + } catch (Exception var2) { + var2.printStackTrace(); + System.exit(0); + } + + return broker; + } + + // // Data Center // public static PowerContainerDatacenter createDatacenter(String name, List hostList, ContainerVmAllocationPolicy vmAllocationPolicy, ContainerAllocationPolicy containerAllocationPolicy) throws Exception { // String arch = "x86"; @@ -252,251 +307,6 @@ public static ContainerDatacenter createDatacenter(String name, Class vms, - List containers, - double lastClock, - String experimentName, - boolean outputInCsv, - String outputFolder) { - Log.enable(); - List hosts = datacenter.getHostList(); - - int numberOfHosts = hosts.size(); - int numberOfVms = vms.size(); - - double totalSimulationTime = lastClock; - double energy = datacenter.getPower() / (3600 * 1000); - int numberOfVmMigrations = datacenter.getVmMigrationCount(); - - Map slaMetrics = getSlaMetrics(vms); - - double slaOverall = slaMetrics.get("overall"); - double slaAverage = slaMetrics.get("average"); - double slaDegradationDueToMigration = slaMetrics.get("underallocated_migration"); - // double slaTimePerVmWithMigration = slaMetrics.get("sla_time_per_vm_with_migration"); - // double slaTimePerVmWithoutMigration = - // slaMetrics.get("sla_time_per_vm_without_migration"); - // double slaTimePerHost = getSlaTimePerHost(hosts); - double slaTimePerActiveHost = getSlaTimePerActiveHost(hosts); - - double sla = slaTimePerActiveHost * slaDegradationDueToMigration; - - List timeBeforeHostShutdown = getTimesBeforeHostShutdown(hosts); - - int numberOfHostShutdowns = timeBeforeHostShutdown.size(); - - double meanTimeBeforeHostShutdown = Double.NaN; - double stDevTimeBeforeHostShutdown = Double.NaN; - if (!timeBeforeHostShutdown.isEmpty()) { - meanTimeBeforeHostShutdown = MathUtil.mean(timeBeforeHostShutdown); - stDevTimeBeforeHostShutdown = MathUtil.stDev(timeBeforeHostShutdown); - } - - List timeBeforeVmMigration = getTimesBeforeVmMigration(vms); - double meanTimeBeforeVmMigration = Double.NaN; - double stDevTimeBeforeVmMigration = Double.NaN; - if (!timeBeforeVmMigration.isEmpty()) { - meanTimeBeforeVmMigration = MathUtil.mean(timeBeforeVmMigration); - stDevTimeBeforeVmMigration = MathUtil.stDev(timeBeforeVmMigration); - } - List timeBeforeContainerMigration = getTimesBeforeContainerMigration(containers); - double meanTimeBeforeContainerMigration = Double.NaN; - double stDevTimeBeforeContainerMigration = Double.NaN; - if (!timeBeforeContainerMigration.isEmpty()) { - meanTimeBeforeContainerMigration = MathUtil.mean(timeBeforeContainerMigration); - stDevTimeBeforeContainerMigration = MathUtil.stDev(timeBeforeContainerMigration); - } - - if (outputInCsv) { - // We create the logging folders - File folder = new File(outputFolder); - if (!folder.exists()) { - folder.mkdir(); - } - File folder1 = new File(outputFolder + "/stats"); - if (!folder1.exists()) { - folder1.mkdir(); - } - File folder2 = new File(outputFolder + "/time_before_host_shutdown"); - if (!folder2.exists()) { - folder2.mkdir(); - } - File folder3 = new File(outputFolder + "/time_before_vm_migration"); - if (!folder3.exists()) { - folder3.mkdir(); - } - File folder4 = new File(outputFolder + "/metrics"); - if (!folder4.exists()) { - folder4.mkdir(); - } - - - StringBuilder data = new StringBuilder(); - String delimeter = ","; - - data.append(experimentName + delimeter); - data.append(parseExperimentName(experimentName)); - data.append(String.format("%d", numberOfHosts) + delimeter); - data.append(String.format("%d", numberOfVms) + delimeter); - data.append(String.format("%.2f", totalSimulationTime) + delimeter); - data.append(String.format("%.5f", energy) + delimeter); -// data.append(String.format("%d", numberOfMigrations) + delimeter); - data.append(String.format("%.10f", sla) + delimeter); - data.append(String.format("%.10f", slaTimePerActiveHost) + delimeter); - data.append(String.format("%.10f", slaDegradationDueToMigration) + delimeter); - data.append(String.format("%.10f", slaOverall) + delimeter); - data.append(String.format("%.10f", slaAverage) + delimeter); -// data.append(String.format("%.5f", slaTimePerVmWithMigration) + delimeter); - // data.append(String.format("%.5f", slaTimePerVmWithoutMigration) + delimeter); - // data.append(String.format("%.5f", slaTimePerHost) + delimeter); - data.append(String.format("%d", numberOfHostShutdowns) + delimeter); - data.append(String.format("%.2f", meanTimeBeforeHostShutdown) + delimeter); - data.append(String.format("%.2f", stDevTimeBeforeHostShutdown) + delimeter); - data.append(String.format("%.2f", meanTimeBeforeVmMigration) + delimeter); - data.append(String.format("%.2f", stDevTimeBeforeVmMigration) + delimeter); - - if (datacenter.getVmAllocationPolicy() instanceof PowerContainerVmAllocationPolicyMigrationAbstract) { - PowerContainerVmAllocationPolicyMigrationAbstract vmAllocationPolicy = (PowerContainerVmAllocationPolicyMigrationAbstract) datacenter - .getVmAllocationPolicy(); - - double executionTimeVmSelectionMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryVmSelection()); - double executionTimeVmSelectionStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryVmSelection()); - double executionTimeHostSelectionMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryHostSelection()); - double executionTimeHostSelectionStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryHostSelection()); - double executionTimeVmReallocationMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryVmReallocation()); - double executionTimeVmReallocationStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryVmReallocation()); - double executionTimeTotalMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryTotal()); - double executionTimeTotalStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryTotal()); - - data.append(String.format("%.5f", executionTimeVmSelectionMean) + delimeter); - data.append(String.format("%.5f", executionTimeVmSelectionStDev) + delimeter); - data.append(String.format("%.5f", executionTimeHostSelectionMean) + delimeter); - data.append(String.format("%.5f", executionTimeHostSelectionStDev) + delimeter); - data.append(String.format("%.5f", executionTimeVmReallocationMean) + delimeter); - data.append(String.format("%.5f", executionTimeVmReallocationStDev) + delimeter); - data.append(String.format("%.5f", executionTimeTotalMean) + delimeter); - data.append(String.format("%.5f", executionTimeTotalStDev) + delimeter); - - writeMetricHistory(hosts, vmAllocationPolicy, outputFolder + "/metrics/" + experimentName - + "_metric"); - } - - data.append("\n"); - - writeDataRow(data.toString(), outputFolder + "/stats/" + experimentName + "_stats.csv"); - writeDataColumn(timeBeforeHostShutdown, outputFolder + "/time_before_host_shutdown/" - + experimentName + "_time_before_host_shutdown.csv"); - writeDataColumn(timeBeforeContainerMigration, outputFolder + "/time_before_vm_migration/" - + experimentName + "_time_before_vm_migration.csv"); - - } else { - Log.setDisabled(false); - Log.printLine(); - Log.printLine(String.format("Experiment name: " + experimentName)); - Log.printLine(String.format("Number of hosts: " + numberOfHosts)); - Log.printLine(String.format("Number of VMs: " + numberOfVms)); - Log.printLine(String.format("Total simulation time: %.2f sec", totalSimulationTime)); - Log.printLine(String.format("Energy consumption: %.2f kWh", energy)); -// Log.printLine(String.format("Number of VM migrations: %d", numberOfMigrations)); - Log.printLine(String.format("SLA: %.5f%%", sla * 100)); - Log.printLine(String.format( - "SLA perf degradation due to migration: %.2f%%", - slaDegradationDueToMigration * 100)); - Log.printLine(String.format("SLA time per active host: %.2f%%", slaTimePerActiveHost * 100)); - Log.printLine(String.format("Overall SLA violation: %.2f%%", slaOverall * 100)); - Log.printLine(String.format("Average SLA violation: %.2f%%", slaAverage * 100)); - // Log.printLine(String.format("SLA time per VM with migration: %.2f%%", - // slaTimePerVmWithMigration * 100)); - // Log.printLine(String.format("SLA time per VM without migration: %.2f%%", - // slaTimePerVmWithoutMigration * 100)); - // Log.printLine(String.format("SLA time per host: %.2f%%", slaTimePerHost * 100)); - Log.printLine(String.format("Number of host shutdowns: %d", numberOfHostShutdowns)); - Log.printLine(String.format( - "Mean time before a host shutdown: %.2f sec", - meanTimeBeforeHostShutdown)); - Log.printLine(String.format( - "StDev time before a host shutdown: %.2f sec", - stDevTimeBeforeHostShutdown)); - Log.printLine(String.format( - "Mean time before a VM migration: %.2f sec", - meanTimeBeforeVmMigration)); - Log.printLine(String.format( - "StDev time before a VM migration: %.2f sec", - stDevTimeBeforeVmMigration)); - Log.printLine(String.format( - "Mean time before a Container migration: %.2f sec", - meanTimeBeforeContainerMigration)); - Log.printLine(String.format( - "StDev time before a Container migration: %.2f sec", - stDevTimeBeforeContainerMigration)); - - if (datacenter.getVmAllocationPolicy() instanceof PowerContainerVmAllocationPolicyMigrationAbstract) { - PowerContainerVmAllocationPolicyMigrationAbstract vmAllocationPolicy = (PowerContainerVmAllocationPolicyMigrationAbstract) datacenter - .getVmAllocationPolicy(); - - double executionTimeVmSelectionMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryVmSelection()); - double executionTimeVmSelectionStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryVmSelection()); - double executionTimeHostSelectionMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryHostSelection()); - double executionTimeHostSelectionStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryHostSelection()); - double executionTimeVmReallocationMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryVmReallocation()); - double executionTimeVmReallocationStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryVmReallocation()); - double executionTimeTotalMean = MathUtil.mean(vmAllocationPolicy - .getExecutionTimeHistoryTotal()); - double executionTimeTotalStDev = MathUtil.stDev(vmAllocationPolicy - .getExecutionTimeHistoryTotal()); - - Log.printLine(String.format( - "Execution time - VM selection mean: %.5f sec", - executionTimeVmSelectionMean)); - Log.printLine(String.format( - "Execution time - VM selection stDev: %.5f sec", - executionTimeVmSelectionStDev)); - Log.printLine(String.format( - "Execution time - host selection mean: %.5f sec", - executionTimeHostSelectionMean)); - Log.printLine(String.format( - "Execution time - host selection stDev: %.5f sec", - executionTimeHostSelectionStDev)); - Log.printLine(String.format( - "Execution time - VM reallocation mean: %.5f sec", - executionTimeVmReallocationMean)); - Log.printLine(String.format( - "Execution time - VM reallocation stDev: %.5f sec", - executionTimeVmReallocationStDev)); - Log.printLine(String.format("Execution time - total mean: %.5f sec", executionTimeTotalMean)); - Log.printLine(String - .format("Execution time - total stDev: %.5f sec", executionTimeTotalStDev)); - } - Log.printLine(); - } - - Log.setDisabled(true); - } /** * Gets the times before vm migration. @@ -859,20 +669,25 @@ public static void printMetricHistory( } } - public static void printResultsNew(PowerContainerDatacenter datacenter, + public static void printResults(PowerContainerDatacenter datacenter, ContainerDatacenterBroker broker, double lastClock, String experimentName, boolean outputInCsv, - String outputFolder) throws IOException { + String outputFolder, + int numberOfRequestedContainers) throws IOException { List vms = broker.getVmsCreatedList(); - List containers = broker.getContainersCreatedList(); + boolean writeHeader = false; + List createdContainers = broker.getContainersCreatedList(); + List cloudlets = broker.getCloudletReceivedList(); + Log.enable(); List hosts = datacenter.getHostList(); Map slaMetrics = getSlaMetrics(vms); String[] msg = { "ExperimentName","hostSelectionPolicy","vmAllocationPolicy", "OLThreshold","ULThreshold", "VMSPolicy","ContainerSpolicy","ContainerPlacement","Percentile", "numberOfHosts", "numberOfVms", + "numberOfContainers", "totalSimulationTime", "slaOverall", "slaAverage", @@ -901,13 +716,18 @@ public static void printResultsNew(PowerContainerDatacenter datacenter, "numberOfOverUtilization", "energy", "CreatedContainers", - "CreatedVms" - - + "CreatedVms", + "meanTimeCloudletFinishTime", + "stDevTimeCloudletFinishTime", + "medTimeCloudletFinishTime", }; int numberOfHosts = hosts.size(); - int numberOfVms = vms.size(); + int numberOfCreatedVms = vms.size(); + int numberOfRequestedVms = broker.getVmList().size(); + int numberOfCreatedContainers = createdContainers.size(); +// int numberOfRequestedContainers = broker.getContainerList().size(); + double totalSimulationTime = lastClock; double slaOverall = slaMetrics.get("overall"); double slaAverage = slaMetrics.get("average"); @@ -923,7 +743,7 @@ public static void printResultsNew(PowerContainerDatacenter datacenter, medTimeBeforeHostShutdown = MathUtil.median(timeBeforeHostShutdown); } - List timeBeforeContainerMigration = getTimesBeforeContainerMigration(containers); + List timeBeforeContainerMigration = getTimesBeforeContainerMigration(createdContainers); double meanTimeBeforeContainerMigration = Double.NaN; double stDevTimeBeforeContainerMigration = Double.NaN; double medTimeBeforeContainerMigration = Double.NaN; @@ -973,27 +793,48 @@ public static void printResultsNew(PowerContainerDatacenter datacenter, int totalContainerMigration =0; int totalVmMigration =0; int totalVmCreated =0; + int totalContainersCreated=0; + if (datacenter instanceof PowerContainerDatacenterCM) { totalContainerMigration = ((PowerContainerDatacenterCM) datacenter).getContainerMigrationCount(); totalVmMigration = ((PowerContainerDatacenterCM) datacenter).getVmMigrationCount(); totalVmCreated = ((PowerContainerDatacenterCM) datacenter).getNewlyCreatedVms(); + totalVmCreated = datacenter.getNumberOfVms(); + totalContainersCreated = datacenter.getNumberOfContainers(); + +// data.append(String.format("%d", broker.getContainersCreated()) + delimeter); +// data.append(String.format("%d", broker.getNumberOfCreatedVMs()) + delimeter); } + PowerContainerVmAllocationPolicyMigrationAbstract vmAllocationPolicy = (PowerContainerVmAllocationPolicyMigrationAbstract) datacenter .getVmAllocationPolicy(); int numberOfOverUtilization = getNumberofOverUtilization(hosts, vmAllocationPolicy); double energy = datacenter.getPower() / (3600 * 1000); - //Now we create the log we need + // Calculate the Successfull returned finishtimes for cloudlets + List cloudletFinishTimes = getCloudletFinishTimes(cloudlets); + double meanTimeCloudletFinishTime = Double.NaN; + double stDevCloudletFinishTime = Double.NaN; + double medCloudletFinishTime = Double.NaN; + if (!cloudletFinishTimes.isEmpty()) { + meanTimeCloudletFinishTime = MathUtil.mean(cloudletFinishTimes); + stDevCloudletFinishTime = MathUtil.stDev(cloudletFinishTimes); + medCloudletFinishTime = MathUtil.median(cloudletFinishTimes); + } + + + // Now we create the log we need StringBuilder data = new StringBuilder(); String delimeter = ","; data.append(experimentName + delimeter); data.append(parseExperimentName(experimentName)); data.append(String.format("%d", numberOfHosts) + delimeter); - data.append(String.format("%d", numberOfVms) + delimeter); + data.append(String.format("%d", numberOfRequestedVms) + delimeter); + data.append(String.format("%d", numberOfRequestedContainers) + delimeter); data.append(String.format("%.2f", totalSimulationTime) + delimeter); data.append(String.format("%.10f", slaOverall) + delimeter); data.append(String.format("%.10f", slaAverage) + delimeter); @@ -1023,6 +864,9 @@ public static void printResultsNew(PowerContainerDatacenter datacenter, data.append(String.format("%.5f", energy) + delimeter); data.append(String.format("%d", broker.getContainersCreated()) + delimeter); data.append(String.format("%d", broker.getNumberOfCreatedVMs()) + delimeter); + data.append(String.format("%.10f", meanTimeCloudletFinishTime) + delimeter); + data.append(String.format("%.10f", stDevCloudletFinishTime) + delimeter); + data.append(String.format("%.10f", medCloudletFinishTime) + delimeter); // data.append(String.format("%.10f", sla) + delimeter); // data.append(String.format("%.10f", slaDegradationDueToMigration) + delimeter); @@ -1038,8 +882,8 @@ public static void printResultsNew(PowerContainerDatacenter datacenter, if (!folder1.exists()) { folder1.mkdir(); } - String beforShutDown = outputFolder + "/time_before_host_shutdown/"+experimentName.substring(0,index); - File folder2 = new File(beforShutDown); + String beforeShutDown = outputFolder + "/time_before_host_shutdown/"+experimentName.substring(0,index); + File folder2 = new File(beforeShutDown); File parent2 = folder2.getParentFile(); if(!parent2.exists() && !parent2.mkdirs()){ throw new IllegalStateException("Couldn't create dir: " + parent2); @@ -1071,32 +915,37 @@ public static void printResultsNew(PowerContainerDatacenter datacenter, File f = new File(fileAddress); + if(!f.exists()) { + f.createNewFile(); + writeHeader = true; + } CSVWriter writer = new CSVWriter(new FileWriter(fileAddress, true), ',',CSVWriter.NO_QUOTE_CHARACTER); File parent = f.getParentFile(); if(!parent.exists() && !parent.mkdirs()){ throw new IllegalStateException("Couldn't create dir: " + parent); } - if(!f.exists()) { - f.createNewFile(); -// writer.writeNext("\n") - } int temp = index; - if(experimentName.substring(index).startsWith("_1") && experimentName.length()-2 == temp){ -// CSVWriter writer1 = new CSVWriter(new FileWriter(fileAddress, true), ',',CSVWriter.NO_QUOTE_CHARACTER); + // It's assumed that runTime number at the end indicates the need to write the header file + // instead if the file did not exist that should indicate that the file already exist and add the header + // NOTE: This can result into having multiple entries with the same experiment name, however, at least the + // header does not get duplicated. +// if(experimentName.substring(index).startsWith("_1") && experimentName.length()-2 == temp) + if (writeHeader) { writer.writeNext(msg); } - writer.writeNext(new String[]{data.toString()}); - writer.flush(); - writer.close(); - + String[] entries = data.toString().split(","); +// writer.writeNext(new String[]{data.toString()}); + writer.writeNext(entries); + writer.flush(); + writer.close(); - writeDataColumn(timeBeforeHostShutdown, beforShutDown+"/"+ experimentName + "_time_before_host_shutdown.csv"); + writeDataColumn(timeBeforeHostShutdown, beforeShutDown+"/"+ experimentName + "_time_before_host_shutdown.csv"); writeDataColumn(timeBeforeContainerMigration, beforeMigrate+"/"+experimentName+ "_time_before_vm_migration.csv"); - + printCloudletList(cloudlets); } @@ -1127,6 +976,53 @@ public static int getNumberofOverUtilization(List hosts } + /** + * Prints the Cloudlet objects. + * + * @param list list of Cloudlets + */ + public static void printCloudletList(List list) { + int size = list.size(); + + String indent = " "; + Log.printLine(); + Log.printLine("========== OUTPUT =========="); + Log.printLine("Cloudlet ID" + indent + "STATUS" + indent + + "Data center ID" + indent + "VM ID" + indent + "Time" + indent + + "Start Time" + indent + "Finish Time"); + + DecimalFormat dft = new DecimalFormat("###.##"); + + list.forEach(cloudlet->{ + Log.print(indent + cloudlet.getCloudletId() + indent + indent); + + if (cloudlet.getCloudletStatusString() == "Success") { + Log.print("SUCCESS"); + + Log.printLine(indent + indent + cloudlet.getResourceId() + + indent + indent + indent + cloudlet.getVmId() + + indent + indent + + dft.format(cloudlet.getActualCPUTime()) + indent + + indent + dft.format(cloudlet.getExecStartTime()) + + indent + indent + + dft.format(cloudlet.getFinishTime())); + } + }); + } + + + public static List getCloudletFinishTimes(List list) { + int size = list.size(); + List result = new ArrayList<>();; + + // Iterate through each and build a list of successfull finish times. + list.forEach(cloudlet->{ + if (cloudlet.getCloudletStatusString() == "Success") + result.add(cloudlet.getFinishTime()); + }); + + return result; + } } diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunConfig.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunConfig.java new file mode 100644 index 000000000..63a5f5bba --- /dev/null +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunConfig.java @@ -0,0 +1,170 @@ +package org.cloudbus.cloudsim.examples.container; + +import java.nio.file.Paths; + +/** + * Created by henri.vandenbulk on 3/20/17. + */ +public class RunConfig { + + private String containerType = ConstantsExamples.CONTAINER_VM_TYPE; + private int numberHosts = ConstantsExamples.NUMBER_HOSTS; + private int numberVms = ConstantsExamples.NUMBER_VMS; + private int numberCloudlets = ConstantsExamples.NUMBER_CLOUDLETS; + + private boolean enableOutput = true; + private boolean outputToFile = true; + + private String inputFolder; + private String outputFolder; + private String vmAllocationPolicy = "MSThreshold-Under_0.80_0.70"; // DVFS policy without VM migrations + private String containerSelectionPolicy = "Cor"; + private String containerAllocationPolicy = "Simple"; + private String hostSelectionPolicy = "FirstFit"; + private String vmSelectionPolicy = "VmMaxC"; +// private double overBookingFactor + + private int runTime = 1; + private int repeat = 100; + + public String getContainerAllocationPolicy() { + return this.containerAllocationPolicy; + } + + public void setContainerAllocationPolicy(String containerAllocationPolicy) { + this.containerAllocationPolicy = containerAllocationPolicy; + } + + public String getContainerType() { + return containerType; + } + + public void setContainerType(String containerType) { + this.containerType = containerType; + } + + public int getNumberHosts() { + return numberHosts; + } + + public void setNumberHosts(int numberHosts) { + this.numberHosts = numberHosts; + } + + public int getNumberVms() { + return numberVms; + } + + public void setNumberVms(int numberVms) { + this.numberVms = numberVms; + } + + public int getNumberCloudlets() { + return numberCloudlets; + } + + public void setNumberCloudlets(int numberCloudlets) { + this.numberCloudlets = numberCloudlets; + } + + public boolean isEnableOutput() { + return enableOutput; + } + + public void setEnableOutput(boolean enableOutput) { + this.enableOutput = enableOutput; + } + + public boolean isOutputToFile() { + return outputToFile; + } + + public void setOutputToFile(boolean outputToFile) { + this.outputToFile = outputToFile; + } + + public String getInputFolder() { + return inputFolder; + } + + public void setInputFolder(String inputFolder) { + this.inputFolder = inputFolder; + } + + public String getOutputFolder() { + return outputFolder; + } + + public void setOutputFolder(String outputFolder) { + this.outputFolder = outputFolder; + } + + public String getVmAllocationPolicy() { + return vmAllocationPolicy; + } + + public void setVmAllocationPolicy(String vmAllocationPolicy) { + this.vmAllocationPolicy = vmAllocationPolicy; + } + + public String getContainerSelectionPolicy() { + return containerSelectionPolicy; + } + + public void setContainerSelectionPolicy(String containerSelectionPolicy) { + this.containerSelectionPolicy = containerSelectionPolicy; + } + + public String getHostSelectionPolicy() { + return hostSelectionPolicy; + } + + public void setHostSelectionPolicy(String hostSelectionPolicy) { + this.hostSelectionPolicy = hostSelectionPolicy; + } + + public String getVmSelectionPolicy() { + return vmSelectionPolicy; + } + + public void setVmSelectionPolicy(String vmSelectionPolicy) { + this.vmSelectionPolicy = vmSelectionPolicy; + } + + public int getRunTime() { + return this.runTime; + } + + public void setRunTime(int runTime) { + this.runTime = runTime; + } + + public int getRepeat() { + return this.repeat; + } + + public void setRepeat(int repeat) { + this.repeat = repeat; + } + + @Override + public String toString() { + return "RunConfig{" + + "containerType='" + containerType + '\'' + + ", numberHosts=" + numberHosts + + ", numberVms=" + numberVms + + ", numberCloudlets=" + numberCloudlets + + ", enableOutput=" + enableOutput + + ", outputToFile=" + outputToFile + + ", inputFolder='" + inputFolder + '\'' + + ", outputFolder='" + outputFolder + '\'' + + ", vmAllocationPolicy='" + vmAllocationPolicy + '\'' + + ", containerSelectionPolicy='" + containerSelectionPolicy + '\'' + + ", containerAllocationPolicy='" + containerAllocationPolicy + '\'' + + ", hostSelectionPolicy='" + hostSelectionPolicy + '\'' + + ", vmSelectionPolicy='" + vmSelectionPolicy + '\'' + + ", runTime=" + runTime + + ", repeat=" + repeat + '}'; + } + +} diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerAbs.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerAbs.java index c4b3c854d..647575bb1 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerAbs.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerAbs.java @@ -1,5 +1,6 @@ package org.cloudbus.cloudsim.examples.container; +import org.cloudbus.cloudsim.DatacenterBroker; import org.cloudbus.cloudsim.Log; import org.cloudbus.cloudsim.container.containerPlacementPolicies.*; import org.cloudbus.cloudsim.container.containerSelectionPolicies.PowerContainerSelectionPolicy; @@ -24,6 +25,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.List; +import java.util.Objects; /** * The RunnerAbs Class is the modified version of {@link org.cloudbus.cloudsim.examples.power.RunnerAbstract} @@ -33,6 +35,7 @@ public abstract class RunnerAbs { private static boolean enableOutput; protected static ContainerDatacenterBroker broker; +// protected static DatacenterBroker broker; /** * The vm list. */ @@ -63,8 +66,41 @@ public abstract class RunnerAbs { private String runTime; + public void setRc(RunConfig rc) { + this.rc = rc; + } + + RunConfig rc; + + + public RunnerAbs () { + + } public RunnerAbs(boolean enableOutput, boolean outputToFile, String inputFolder, String outputFolder, String vmAllocationPolicy, String containerAllocationPolicy, String vmSelectionPolicy, String containerSelectionPolicy, String hostSelectionPolicy, double overBookingFactor, String runTime, String logAddress) { + + initializeAndStart( enableOutput, outputToFile, inputFolder, outputFolder, vmAllocationPolicy, containerAllocationPolicy, vmSelectionPolicy, containerSelectionPolicy, hostSelectionPolicy, overBookingFactor, runTime, logAddress); + + } + + public void initializeAndStart(double overBookingFactor) { + if (rc != null) { + initializeAndStart( + rc.isEnableOutput(), + rc.isOutputToFile(), + rc.getInputFolder(), + rc.getOutputFolder(), + rc.getVmAllocationPolicy(), + rc.getContainerAllocationPolicy(), + rc.getVmSelectionPolicy(), + rc.getContainerSelectionPolicy(), + rc.getHostSelectionPolicy(), + overBookingFactor, Integer.toString(rc.getRunTime()), rc.getOutputFolder() + ); + } + } + + public void initializeAndStart(boolean enableOutput, boolean outputToFile, String inputFolder, String outputFolder, String vmAllocationPolicy, String containerAllocationPolicy, String vmSelectionPolicy, String containerSelectionPolicy, String hostSelectionPolicy, double overBookingFactor, String runTime, String logAddress) { setOverBookingFactor(overBookingFactor); setRunTime(runTime); setLogAddress(logAddress); @@ -97,7 +133,7 @@ public void setRunTime(String runTime) { this.runTime = runTime; } - protected void initLogOutput(boolean enableOutput, boolean outputToFile, String outputFolder, String vmAllocationPolicy, String vmSelectionPolicy, String containerSelectionPolicy, String hostSelectionPolicy) throws IOException, FileNotFoundException { + protected void initLogOutput(boolean enableOutput, boolean outputToFile, String outputFolder, String vmAllocationPolicy, String vmSelectionPolicy, String containerSelectionPolicy, String hostSelectionPolicy) throws IOException, FileNotFoundException { this.setEnableOutput(enableOutput); Log.setDisabled(!this.isEnableOutput()); // OutputStream out = new FileOutputStream("/home/sareh/Dropbox/programming/Results/log.txt"); @@ -178,18 +214,25 @@ protected void start(String experimentName, String outputFolder, ContainerVmAllo // PowerContainerDatacenter e = (PowerContainerDatacenter) HelperEx.createDatacenter("Datacenter", PowerContainerDatacenter.class, hostList, vmAllocationPolicy, containerAllocationPolicy); vmAllocationPolicy.setDatacenter(e); e.setDisableVmMigrations(false); + broker.submitVmList(vmList); broker.submitContainerList(containerList); broker.submitCloudletList(cloudletList.subList(0, containerList.size())); - ; - CloudSim.terminateSimulation(86400.0D); + + CloudSim.terminateSimulation(ConstantsExamples.SIMULATION_LIMIT); double lastClock = CloudSim.startSimulation(); List newList = broker.getCloudletReceivedList(); + List submitList = broker.getCloudletSubmittedList(); + + Log.printLine("Requested " + cloudletList.size() + " cloudlets"); Log.printLine("Received " + newList.size() + " cloudlets"); + Log.printLine("Submitted " + submitList.size() + " cloudlets"); CloudSim.stopSimulation(); // HelperEx.printResults(e, broker.getVmsCreatedList(),broker.getContainersCreatedList() ,lastClock, experimentName, true, outputFolder); - HelperEx.printResultsNew(e, broker, lastClock, experimentName, true, outputFolder); + + HelperEx.printResults(e, broker, lastClock, experimentName, true, outputFolder, containerList.size()); + } catch (Exception var8) { var8.printStackTrace(); Log.printLine("The simulation has been terminated due to an unexpected error"); @@ -259,7 +302,7 @@ protected ContainerVmAllocationPolicy getVmAllocationPolicy(String vmAllocationP protected ContainerAllocationPolicy getContainerAllocationPolicy(String containerAllocationPolicyName) { ContainerAllocationPolicy containerAllocationPolicy; - if (containerAllocationPolicyName == "Simple") { + if (Objects.equals(containerAllocationPolicyName, "Simple")) { containerAllocationPolicy = new PowerContainerAllocationPolicySimple(); // DVFS policy without VM migrations } else { @@ -273,42 +316,52 @@ protected ContainerAllocationPolicy getContainerAllocationPolicy(String containe } protected ContainerPlacementPolicy getContainerPlacementPolicy(String name) { - ContainerPlacementPolicy placementPolicy; - switch (name) { - case "LeastFull": - placementPolicy = new ContainerPlacementPolicyLeastFull(); - break; - case "MostFull": - placementPolicy = new ContainerPlacementPolicyMostFull(); - break; - - case "FirstFit": - placementPolicy = new ContainerPlacementPolicyFirstFit(); - break; - case "Random": - placementPolicy = new ContainerPlacementPolicyRandomSelection(); - break; - default: - placementPolicy = null; - System.out.println("The container placement policy is not defined"); - break; + ContainerPlacementPolicy placementPolicy = null; + ClassLoader classLoader = RunnerAbs.class.getClassLoader(); + + try { + Class reflectionClass = classLoader.loadClass("org.cloudbus.cloudsim.container.containerPlacementPolicies.ContainerPlacementPolicy" + name); + placementPolicy = (ContainerPlacementPolicy) reflectionClass.newInstance(); + } catch (Exception e) { + placementPolicy = null; + System.out.println("The container placement policy is not defined"); } + +// switch (name) { +// case "LeastFull": +// placementPolicy = new ContainerPlacementPolicyLeastFull(); +// break; +// case "MostFull": +// placementPolicy = new ContainerPlacementPolicyMostFull(); +// break; +// +// case "FirstFit": +// placementPolicy = new ContainerPlacementPolicyFirstFit(); +// break; +// case "Random": +// placementPolicy = new ContainerPlacementPolicyRandomSelection(); +// break; +// default: +// placementPolicy = null; +// System.out.println("The container placement policy is not defined"); +// break; +// } return placementPolicy; } protected HostSelectionPolicy getHostSelectionPolicy(String hostSelectionPolicyName) { Object hostSelectionPolicy = null; - if (hostSelectionPolicyName == "FirstFit") { + if (Objects.equals(hostSelectionPolicyName, "FirstFit")) { hostSelectionPolicy = new HostSelectionPolicyFirstFit(); - } else if (hostSelectionPolicyName == "LeastFull") { + } else if (Objects.equals(hostSelectionPolicyName, "LeastFull")) { hostSelectionPolicy = new HostSelectionPolicyLeastFull(); - } else if (hostSelectionPolicyName == "MostFull") { + } else if (Objects.equals(hostSelectionPolicyName, "MostFull")) { hostSelectionPolicy = new HostSelectionPolicyMostFull(); @@ -320,7 +373,7 @@ protected HostSelectionPolicy getHostSelectionPolicy(String hostSelectionPolicyN // } - else if (hostSelectionPolicyName == "RandomSelection") { + else if (Objects.equals(hostSelectionPolicyName, "RandomSelection")) { hostSelectionPolicy = new HostSelectionPolicyRandomSelection(); diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerInitiator.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerInitiator.java index 6647684d4..81ad0fac1 100644 --- a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerInitiator.java +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/RunnerInitiator.java @@ -2,6 +2,7 @@ import org.cloudbus.cloudsim.Log; import org.cloudbus.cloudsim.core.CloudSim; +import org.cloudbus.cloudsim.examples.power.Helper; import java.util.Calendar; @@ -12,7 +13,6 @@ public class RunnerInitiator extends RunnerAbs { - /** * Instantiates a new runner. * @@ -36,7 +36,6 @@ public RunnerInitiator( String hostSelectionPolicy, double overBookingFactor, String runTime, String logAddress) { - super(enableOutput, outputToFile, inputFolder, @@ -50,6 +49,33 @@ public RunnerInitiator( } + public RunnerInitiator() { + + } + +// public RunnerInitiator( +// RunConfig rc, +// double overBookingFactor) { +// +// this.rc = rc; +// +// initializeAndStart( +// rc.isEnableOutput(), +// rc.isOutputToFile(), +// rc.getInputFolder(), +// rc.getOutputFolder(), +// rc.getVmAllocationPolicy(), +// rc.getContainerAllocationPolicy(), +// rc.getVmSelectionPolicy(), +// rc.getContainerSelectionPolicy(), +// rc.getHostSelectionPolicy(), +// overBookingFactor, Integer.toString(rc.getRunTime()), rc.getOutputFolder() +// ); +// +// +// +// } + /* * (non-Javadoc) * @@ -58,14 +84,22 @@ public RunnerInitiator( @Override protected void init(String inputFolder, double overBookingFactor) { try { + Log.printLine("Initializing Simulation"); + CloudSim.init(1, Calendar.getInstance(), false); // setOverBookingFactor(overBookingFactor); broker = HelperEx.createBroker(overBookingFactor); + +// broker = HelperEx.createAuctionBroker(overBookingFactor); int brokerId = broker.getId(); - cloudletList = HelperEx.createContainerCloudletList(brokerId, inputFolder, ConstantsExamples.NUMBER_CLOUDLETS); - containerList = HelperEx.createContainerList(brokerId, ConstantsExamples.NUMBER_CLOUDLETS); - vmList = HelperEx.createVmList(brokerId, ConstantsExamples.NUMBER_VMS); - hostList = HelperEx.createHostList(ConstantsExamples.NUMBER_HOSTS); +// cloudletList = HelperEx.createContainerCloudletList(brokerId, inputFolder, ConstantsExamples.NUMBER_CLOUDLETS); + cloudletList = HelperEx.createContainerCloudletList(brokerId, inputFolder, rc.getNumberCloudlets()); +// containerList = HelperEx.createContainerList(brokerId, ConstantsExamples.NUMBER_CLOUDLETS); + containerList = HelperEx.createContainerList(brokerId, rc.getNumberCloudlets()); +// vmList = HelperEx.createVmList(brokerId, ConstantsExamples.NUMBER_VMS, ConstantsExamples.CONTAINER_VM_TYPE); + vmList = HelperEx.createVmList(brokerId, rc.getNumberVms(), rc.getContainerType()); +// hostList = HelperEx.createHostList(ConstantsExamples.NUMBER_HOSTS); + hostList = HelperEx.createHostList(rc.getNumberHosts()); } catch (Exception e) { e.printStackTrace(); diff --git a/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/package-info.java b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/package-info.java new file mode 100644 index 000000000..4df7fe4dd --- /dev/null +++ b/modules/cloudsim-examples/src/main/java/org/cloudbus/cloudsim/examples/container/package-info.java @@ -0,0 +1,4 @@ +/** + * Created by henri.vandenbulk on 3/20/17. + */ +package org.cloudbus.cloudsim.examples.container; \ No newline at end of file diff --git a/modules/cloudsim/pom.xml b/modules/cloudsim/pom.xml index 2ad29baa3..ff2dc62e7 100644 --- a/modules/cloudsim/pom.xml +++ b/modules/cloudsim/pom.xml @@ -6,7 +6,7 @@ org.cloudbus.cloudsim 4.0 - + jar cloudsim cloudsim diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/AuctionException.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/AuctionException.java new file mode 100644 index 000000000..4a6537d67 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/AuctionException.java @@ -0,0 +1,24 @@ +package org.cloudbus.cloudsim.auction; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents a bid from datacenter or a broker + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/7/17 + */ +public class AuctionException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public AuctionException() { + super(); + } + + public AuctionException(String message) { + super(message); + } + +} diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/EntityCharacteristics.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/EntityCharacteristics.java new file mode 100644 index 000000000..ec455fd45 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/EntityCharacteristics.java @@ -0,0 +1,202 @@ +package org.cloudbus.cloudsim.auction; + +/** + * Represents the characteristics in CloudSim environment. + * TODO: DatacenterCharacteristics can extend this class in future. + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/26 + */ +public class EntityCharacteristics { + + /** The architecture. */ + private String architecture; + + /** The os. */ + private String os; + + /** The time zone -- difference from GMT. */ + private double timeZone; + + /** The vmm. */ + private String vmm; + + /** Price/CPU-unit if unit = sec., then G$/CPU-sec. */ + private double costPerSecond; + + /** The cost per mem. */ + private double costPerMem; + + /** The cost per storage. */ + private double costPerStorage; + + /** The cost per bw. */ + private double costPerBw; + + public EntityCharacteristics( + String architecture, + String os, + String vmm, + double timeZone, + double costPerSec, + double costPerMem, + double costPerBw, + double costPerStorage) { + + setArchitecture(architecture); + setOs(os); + setCostPerSecond(costPerSec); + setTimeZone(0.0); + setVmm(vmm); + setCostPerMem(costPerMem); + setCostPerBw(costPerBw); + setCostPerStorage(costPerStorage); + } + + /** + * Get the cost to use memory in this resource. + * + * @return the cost to use memory + */ + public double getCostPerMem() { + return costPerMem; + } + + /** + * Sets cost to use memory. + * + * @param costPerMem cost to use memory + */ + public void setCostPerMem(double costPerMem) { + this.costPerMem = costPerMem; + } + + /** + * Get the cost to use storage in this resource. + * + * @return the cost to use storage + */ + public double getCostPerStorage() { + return costPerStorage; + } + + /** + * Sets cost to use storage. + * + * @param costPerStorage cost to use storage + */ + public void setCostPerStorage(double costPerStorage) { + this.costPerStorage = costPerStorage; + } + + /** + * Get the cost to use bandwidth in this resource. + * + * @return the cost to use bw + */ + public double getCostPerBw() { + return costPerBw; + } + + /** + * Sets cost to use bw cost to use bw. + * + * @param costPerBw the cost per bw + */ + public void setCostPerBw(double costPerBw) { + this.costPerBw = costPerBw; + } + + /** + * Gets the VMM in use in the datacenter. + * + * @return the VMM name + */ + public String getVmm() { + return vmm; + } + + /** + * Sets the vmm. + * + * @param vmm the new vmm + */ + protected void setVmm(String vmm) { + this.vmm = vmm; + } + + /** + * Gets the architecture. + * + * @return the architecture + */ + protected String getArchitecture() { + return architecture; + } + + /** + * Sets the architecture. + * + * @param architecture the new architecture + */ + protected void setArchitecture(String architecture) { + this.architecture = architecture; + } + + /** + * Gets the os. + * + * @return the os + */ + protected String getOs() { + return os; + } + + /** + * Sets the os. + * + * @param os the new os + */ + protected void setOs(String os) { + this.os = os; + } + + /** + * Gets the time zone. + * + * @return the time zone + */ + protected double getTimeZone() { + return timeZone; + } + + /** + * Sets the time zone. + * + * @param timeZone the new time zone + */ + protected void setTimeZone(double timeZone) { + this.timeZone = timeZone; + } + + /** + * Gets the cost per second. + * + * @return the cost per second + */ + public double getCostPerSecond() { + return costPerSecond; + } + + /** + * Sets the cost per second. + * + * @param costPerSecond the new cost per second + */ + protected void setCostPerSecond(double costPerSecond) { + this.costPerSecond = costPerSecond; + } + +} diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AuctionAllocation.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AuctionAllocation.java new file mode 100644 index 000000000..f9fec64d9 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AuctionAllocation.java @@ -0,0 +1,181 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +import org.cloudbus.cloudsim.Vm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents the assignment of offered VMs to requested VMs + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/22 + */ +class AuctionAllocation { + + /** + * Used to maintain which VM from datacenter's bid is assigned to the requested VM. + * 1. Key in first Map is the requested VM from broker + * 2. Key in second Map is the datacenter's bid, from which vm(s) is/are assigned + * 3. Value in second Map is the VM and its amount assigned to 1 from a datacenter's bid + */ + private HashMap> allocations; + + public AuctionAllocation() { + this.allocations = new HashMap>(); + } + + void addAllocation(Vm requestedVM, BidCalculation datacenterBid, + Vm offeredVM, int quantity, double price) { + + if (!this.allocations.containsKey(requestedVM)) { + this.addNewRequestedVM(requestedVM, datacenterBid, offeredVM, quantity, price); + } else { + HashMap datacenterBids = + this.allocations.get(requestedVM); + this.addNewDatacenterBid(datacenterBids, datacenterBid, offeredVM, quantity, price); + } + } + + void removeAllocation(Vm brokerVm) { + this.allocations.remove(brokerVm); + } + + void removeAllocation(Vm brokerVM, BidCalculation datacenterBid) { + HashMap datacenterBids = + this.allocations.get(brokerVM); + datacenterBids.remove(datacenterBid); + } + + private void addNewRequestedVM(Vm requestedVM, BidCalculation datacenterBid, + Vm offeredVM, int quantity, double price) { + + HashMap bids = + new HashMap (); + this.addNewDatacenterBid(bids, datacenterBid, offeredVM, quantity, price); + + this.allocations.put(requestedVM, bids); + } + + private void addNewDatacenterBid(HashMap datacenterBids, + BidCalculation datacenterBid, Vm offeredVM, int quantity, double price) { + datacenterBids.put(datacenterBid, new VmAllocation(offeredVM, quantity, price)); + } + + /** + * Returns the allocated datacenter bids for the broker vm + * @param vm Vm + * @return Set + */ + public Set getAllocatedDatacenterBids(Vm vm) { + HashMap datacenterBids = + this.allocations.get(vm); + if (datacenterBids != null) { + return datacenterBids.keySet(); + } + return null; + } + + /** + * Returns the allocated datacenter VMs for the broke's VM + * @param brokerVM AbstractVm broker's VM + * @param allocatedDatacenterBid BidCalculation datacenter's bid + * @return Vm The allocated datacenter VM + */ + public Vm getAllocatedVM(Vm brokerVM, + BidCalculation allocatedDatacenterBid) { + HashMap datacenterBids = + this.allocations.get(brokerVM); + if (datacenterBids != null && datacenterBids.containsKey(allocatedDatacenterBid)) { + VmAllocation allocatedVM = datacenterBids.get(allocatedDatacenterBid); + + if (allocatedVM != null) { + return allocatedVM.getVm(); + } + } + return null; + } + + /** + * + * @param brokerVM AbstractVm broker's VM + * @param allocatedDatacenterBid BidCalculation datacenter's bid + * @return allocated quantity + */ + public int getAllocatedQuantity(Vm brokerVM, + BidCalculation allocatedDatacenterBid) { + HashMap datacenterBids = + this.allocations.get(brokerVM); + if (datacenterBids != null && datacenterBids.containsKey(allocatedDatacenterBid)) { + VmAllocation allocatedVM = datacenterBids.get(allocatedDatacenterBid); + if (allocatedVM != null) { + return allocatedVM.getAllocatedAmount(); + } + } + return 0; + } + + /** + * + * @param brokerVM Vm broker's VM + * @param allocatedDatacenterBid BidCalculation datacenter's bid + * @return VmAllocation allocated quantity, price, ... + */ + public VmAllocation getVmAllocation(Vm brokerVM, + BidCalculation allocatedDatacenterBid) { + HashMap datacenterBids = + this.allocations.get(brokerVM); + if (datacenterBids != null && datacenterBids.containsKey(allocatedDatacenterBid)) { + VmAllocation allocatedVM = datacenterBids.get(allocatedDatacenterBid); + return allocatedVM; + } + return null; + } + + /** + * Returns the list of requested VMs (in VMAllocation format) for the offeredVM bundled in + * datacenter (wrapped in BidCalculation) + * @param bidCalc BidCalculation The datacenter's bid calculation + * @param offeredVM Vm The offered VM in bidCalc + * @return List list of requested VMs assigned to offeredVM + */ + public List getRequestAllocations(BidCalculation bidCalc, Vm offeredVM) { + List requestAllocations = null; + + Set requestedVMs = this.allocations.keySet(); + if (requestedVMs != null) { + for (Vm requestedVM : requestedVMs) { + HashMap datacenterBidMap = this.allocations.get(requestedVM); + if (datacenterBidMap != null) { + Set datacenterBids = datacenterBidMap.keySet(); + if (datacenterBids != null) { + for (BidCalculation datacenterBid : datacenterBids) { + if (datacenterBid == bidCalc) { + VmAllocation offeredVMAllocation = datacenterBidMap.get(datacenterBid); + if (offeredVMAllocation.getVm() == offeredVM) { + + VmAllocation requestedVMAllocation = new VmAllocation(requestedVM, + offeredVMAllocation.getAllocatedAmount(), + offeredVMAllocation.getAllocationPrice()); + + if (requestAllocations == null) { + requestAllocations = new ArrayList(); + } + requestAllocations.add(requestedVMAllocation); + + } + } + } + } + } + } + } + return requestAllocations; + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AuctionTags.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AuctionTags.java new file mode 100644 index 000000000..e1eea41cf --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AuctionTags.java @@ -0,0 +1,51 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +/** + * This class must be on comply with the attributes in CloudSimTags class + * They integer values must not be interference with each other + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/26 + */ +public class AuctionTags { + // starting constant value for cloud-related tags + private static final int BASE = 0; + + /** + * Denotes an event to register the broker into auction notification service + */ + public static final int REGISTER_BIDDER = BASE + 43; + + /** + * Denotes an event to inform the registered entities (in Auctioneer) + * that auction is started. + */ + public static final int AUCTION_START = BASE + 44; + + /** + * Denotes an event from bidder (datacenter/broker) to Auctioneer to + * bid in auction + */ + public static final int BID_AUCTION = BASE + 45; + + /** + * Denotes an event from Auctioneer to inform the bidder (datacenter/broker) + * that the bidder's bid is accepted or not. + */ + public static final int BID_ACKNOWLEDGE = BASE + 46; + + /** + * Denotes an event to inform the registered entities (in Auctioneer) + * that auction is closed and no more bids are accepted. + */ + public static final int AUCTION_CLOSE = BASE + 47; + + /** + * Denotes an event from Auctioneer to inform the bidders of the + * allocation results. + */ + public static final int ALLOCATION_PUBLICATION = BASE + 48; + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/Auctioneer.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/Auctioneer.java new file mode 100644 index 000000000..7e6fedfa3 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/Auctioneer.java @@ -0,0 +1,586 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +import org.cloudbus.cloudsim.Log; +import org.cloudbus.cloudsim.Vm; +import org.cloudbus.cloudsim.auction.AuctionException; +import org.cloudbus.cloudsim.auction.bid.Bid; +import org.cloudbus.cloudsim.auction.bid.DatacenterBid; +import org.cloudbus.cloudsim.auction.bid.DatacenterBrokerBid; +import org.cloudbus.cloudsim.auction.vm.DatacenterAbstractVm; +import org.cloudbus.cloudsim.auction.vm.VmUtils; +import org.cloudbus.cloudsim.core.CloudSim; +import org.cloudbus.cloudsim.core.SimEntity; +import org.cloudbus.cloudsim.core.SimEvent; + +import java.util.*; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents an auctioneer agent that is responsible to handle an auction + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/7/17 + */ +public class Auctioneer extends SimEntity { + + //Create an auctioneer object + //TODO This attribute must be a member of CloudSim class + /** Auctioneer*/ + private static Auctioneer auctioneer ; + + //TODO This method must be a member of CloudSim class + public static int getAuctioneerEntityId() { + return auctioneer.getId(); + } + + public static void initAuctioneer() { + if (auctioneer ==null) { + auctioneer = new Auctioneer("Auctioneer"); + } + } + + /** + * The required minimum number of registered bidders to start the auction + */ + private static final int MIN_REGISTERED_ENTITIES = 2; + + //TODO decide when to release the following reference at the end of auction + /** + * The real bids are maintained in this list. + */ + private List bidCalcs; + + //TODO decide when to release the following reference little by little maybe when every broker gets its portion + /** + * Contains the assignment of offered VMs to requested VMs + */ + private AuctionAllocation allocations = new AuctionAllocation(); + + /** + * The set contains the id of entities that has requested to get notification + * of auction start. + * The set is cleared after auction end notification. + * Note that a bidder is not necessarily a registered-to-be-notified + * bidder. This means every one can bid the auction away from being + * registered to get notifications or not. + */ + private Set registeredEntityList; + + /** + * Represents if auction is open or not. + */ + private boolean auctionOpen; + + public Auctioneer(String name) { + super(name); + } + + @Override + public void processEvent(SimEvent ev) { + switch (ev.getTag()) { + + case AuctionTags.REGISTER_BIDDER: + this.registerEntity(ev.getSource()); + this.decideStartAuction(); + break; + + case AuctionTags.AUCTION_START: + this.informAuctionStart(); + break; + + case AuctionTags.BID_AUCTION: + this.registerBid((Bid) ev.getData()); + this.decideCloseAuction(); + break; + + case AuctionTags.AUCTION_CLOSE: + this.informAuctionClose(); + break; + } + + } + + private boolean auctionStartNotificationSent; + + private void decideStartAuction() { + /** + * We can imagine if a fixed number of registers were accepted, start the auction + */ + if (!this.auctionStartNotificationSent && + this.registeredEntityList.size() >= Auctioneer.MIN_REGISTERED_ENTITIES) { + sendNow(getId(), AuctionTags.AUCTION_START); + this.auctionStartNotificationSent = true; + this.sentStartAuctionNotifications++; + } + } + + /** + * The amount of START_AUCTION notifications sent to registered entitiyes. + */ + private int sentStartAuctionNotifications; + + /** + * If all registered entities were sent START_AUCTION notification, close the auction + */ + private void decideCloseAuction() { + //The first condition in if clause is to send the inner ACTION_CLOSE notifications once for all + if (this.auctionStartNotificationSent && + this.sentStartAuctionNotifications <= this.registeredEntityList.size()) { + sendNow(getId(), AuctionTags.AUCTION_CLOSE); + this.auctionStartNotificationSent = false; + this.sentStartAuctionNotifications = 0; + } + } + + + @Override + public void startEntity() {} + + @Override + public void shutdownEntity() { + // TODO Auto-generated method stub + + } + + /** + * Register the entity (datacenter, Broker, etc.) to notify it when the auction starts + * @param simEntityID int + */ + public void registerEntity(int simEntityID) { + if (this.registeredEntityList == null) { + this.registeredEntityList = new HashSet(); + } + this.registeredEntityList.add(simEntityID); + } + + /** + * Inform the registered bidders (datacenters, brokers, etc.) that action + * is going to start accepting bids. + */ + public void informAuctionStart() { + this.openAuction(); + if (this.registeredEntityList != null) { + for (int entityID : this.registeredEntityList) { + sendNow(entityID, AuctionTags.AUCTION_START); + } + } + } + + private void openAuction() { + this.auctionOpen = true; + } + + private void closeAuction() { + this.auctionOpen = false; + } + + private boolean isAuctionOpen() { + return this.auctionOpen; + } + + + /** + * Registers a bid from bidders (datacenter, broker) + * @param bid Bid + */ + private void registerBid(Bid bid) { + if (!this.isAuctionOpen()) { + sendNow(bid.getBidderID(), AuctionTags.BID_ACKNOWLEDGE, false); + return; + } + + if (bid instanceof DatacenterBid || bid instanceof DatacenterBrokerBid) { + + if (this.bidCalcs == null) { + this.bidCalcs = new ArrayList(); + } + this.bidCalcs.add(new BidCalculation(bid)); + sendNow(bid.getBidderID(), AuctionTags.BID_ACKNOWLEDGE, true); + + } else { + throw new AuctionException("Not handled Bid type."); + } + + } + + /** + * - Inform the bidders (datacenters and brokers) that action is closed and + * no more request is processed. + * - Clear the list of registered bidders. + * - Compute auction + * - Return results + */ + public void informAuctionClose() { + //Close auction + this.closeAuction(); + if (this.registeredEntityList != null) { + for (int entityID : this.registeredEntityList) { + sendNow(entityID, AuctionTags.AUCTION_CLOSE); + } + this.registeredEntityList = null; + } + + if (this.bidCalcs != null) { + //Compute auction + this.computeAuction(); + + //Return result + this.allocationPublication(); + } + } + + /** + * Calculate the auction assignments (looser, winner and their shares) + */ + private void computeAuction() { + //Separate broker bids and datacenter bids into two bunches + List brokerBidCalcs = getBidCalcs(this.bidCalcs, DatacenterBrokerBid.class); + List datacenterBidCalcs = getBidCalcs(this.bidCalcs, DatacenterBid.class); + + /** + * Order each bunch of bids + */ + + Comparator comparator = new NormComparator();//TODO decide from one of the following comparators: //AverageBidComparator//NormComparator + + //broker bids are ordered in descending order + Collections.sort(brokerBidCalcs, comparator); + printBidCalcs("brokers", brokerBidCalcs); + //datacenter bids are ordered in ascending order + Collections.sort(datacenterBidCalcs, comparator); + printBidCalcs("datacenters", datacenterBidCalcs); + + for (BidCalculation brokerBidCalc : brokerBidCalcs) { + List brokerVMs = brokerBidCalc.getOrderedResources(); + if (brokerVMs != null) { // If broker has request + for (BidCalculation datacenterBidCalc : datacenterBidCalcs) { + /** + * The broker average bid must be equal or greater than the offered average + * bid to let the broker bid accepted. + */ + if (brokerBidCalc.getAverageBid() >= datacenterBidCalc.getAverageBid()) { + List datacenterVMs = datacenterBidCalc.getOrderedResources(); + if (datacenterVMs != null) { // If datacenter has offer + + + this.algorithmEngine(brokerBidCalc, brokerVMs, datacenterBidCalc, datacenterVMs); + + + } // end of if (datacenterVMs != null) + } // end of if (brokerBidCalc.getAverageBid() >= datacenterBidCalc.getAverageBid()) + } // end of for (BidCalculation datacenterBidCalc : datacenterBidCalcs) + + /** + * Check if resources are not completely assigned to broker. + */ + this.satisfactionHandling(brokerBidCalc); + + } // end of if (brokerVMs != null) + } // end of for (BidCalculation brokerBidCalc : brokerBidCalcs) + } + + private void algorithmEngine(BidCalculation brokerBidCalc, List requestedVMs, + BidCalculation datacenterBidCalc, List offeredVMs) { + + for (Vm requestedVM : requestedVMs) { + for (Vm offeredVM : offeredVMs) { + + /** + * See if any amount requested + */ + int requestAmount = brokerBidCalc.getRemainingQuantity(requestedVM); + if (requestAmount == 0) { // If nothing is requested + break; // Process next requested VM + } + + /** + * See if enough amount of resource is offered + */ + int offerAmount = datacenterBidCalc.getRemainingQuantity(offeredVM); + if (offerAmount == 0) { // If nothing is offered + continue; // Process next offered VM + } + + /** + * See if offered VM can satisfy the request + */ + if (VmUtils.canServe(offeredVM, requestedVM)) { + + int assignAmount = (requestAmount <= offerAmount ? requestAmount : offerAmount); + + /** + * Assign mapped-together VMs + */ + this.assignVMs(brokerBidCalc, requestedVM, datacenterBidCalc, offeredVM, assignAmount); + break; + } // end of if (requestedVM.getWeight() <= offeredVM.getWeight()) + }// end of for (Vm offeredVM : offeredVMs) + }// end of for (Vm requestedVM : requestedVMs) + } + + /** + * If a broker is not assigned all its requests, release its assigned resources. + * @param brokerBidCalc BidCalculation + */ + private void satisfactionHandling(BidCalculation brokerBidCalc) { + if (!brokerBidCalc.isSatisfied()) { + + /** + * Get allocated broker VMs + */ + Set brokerAllocatedVMs = brokerBidCalc.getAllocatedVMs(); + if (brokerAllocatedVMs != null) { + for (Vm brokerVM : brokerAllocatedVMs) { + + /** + * Get allocated datacenter-bids for a broker-VM + */ + Set allocatedDatacenterBids = + this.allocations.getAllocatedDatacenterBids(brokerVM); + + if (allocatedDatacenterBids != null) { + for (BidCalculation allocatedDatacenterBid : allocatedDatacenterBids) { + /** + * Get allocated datacenter-VMs in the 'datacenter-bid for a broker-VM' + */ + Vm allocatedDatacenterVM = this.allocations.getAllocatedVM(brokerVM, allocatedDatacenterBid); + if (allocatedDatacenterVM != null) { + int allocatedQuantity = this.allocations.getAllocatedQuantity(brokerVM, + allocatedDatacenterBid); + + /** + * Roll back the price and requested amount + */ + this.releaseVMsStep1(brokerBidCalc, brokerVM, + allocatedDatacenterBid, allocatedDatacenterVM, allocatedQuantity); + + } // if (allocatedDatacenterVMs != null) + } // for (BidCalculation allocatedDatacenterBid : allocatedDatacenterBids) + + /** + * To avoid ConcurrentModificationException, we do this operation out + * of the preceding for loop. + */ + this.releaseVMsStep2(brokerVM); + + + } // if (allocatedDatacenterBids != null) + } // end of for (Vm brokerVM : brokerAllocatedVMs) + } // end of if (brokerAllocatedVMs != null) + } // if satisfied + } + + /** + * Assigns matched VMs together, specifying the amount and price of + * assignment for both sides (broker and datacenter) + */ + private void assignVMs(BidCalculation brokerBidCalc, Vm requestedVM, + BidCalculation datacenterBidCalc, Vm offeredVM, int assignAmount) { + + /** + * Compute price + */ + double payPrice = computePrice(brokerBidCalc, datacenterBidCalc, assignAmount); + + /** + * A number of requests were accepted therefore update the + * amount of requests for broker side + * Update the price which broker must pay + */ + brokerBidCalc.assignAllocation(requestedVM, assignAmount, payPrice); + /** + * A number of offers were offered therefore update the + * amount of offers for datacenter side + * Update the price which datacenter must get + */ + datacenterBidCalc.assignAllocation(offeredVM, assignAmount, payPrice); + + this.allocations.addAllocation(requestedVM, datacenterBidCalc, offeredVM, assignAmount, payPrice); + } + + /** + * Releases assigned together VMs, subtracting the amount and price of + * assignment for both sides (broker and datacenter) + */ + private void releaseVMsStep1(BidCalculation brokerBidCalc, Vm brokerVM, + BidCalculation datacenterBidCalc, Vm offeredVM, int assignAmount) { + + /** + * Compute price + */ + double subtractPrice = computePrice(brokerBidCalc, datacenterBidCalc, assignAmount); + + /** + * A number of requests were released therefore update the + * amount of requests for broker side + * Update the price which broker must pay + */ + brokerBidCalc.releaseAllocation(brokerVM, assignAmount, subtractPrice); + /** + * A number of offers were released therefore update the + * amount of offers for datacenter side + * Update the price which datacenter must get + */ + datacenterBidCalc.releaseAllocation(offeredVM, assignAmount, subtractPrice); + } + + /** + * Releases assigned datacenter bids to requested broker VMs from main allocations + * @param brokerVM Vm + */ + private void releaseVMsStep2(Vm brokerVM) { + this.allocations.removeAllocation(brokerVM); + } + + + private static double computePrice(BidCalculation brokerBidCalc, + BidCalculation datacenterBidCalc, int assignAmount) { + return ((brokerBidCalc.getAverageBid() + datacenterBidCalc.getAverageBid()) / 2); + } + + private static List getBidCalcs(List bidCalculations, Class class1) { + List bidCalcs = null; + for (BidCalculation bidCalc : bidCalculations) { + if (bidCalc.getBidderType() == class1) { + if (bidCalcs == null) { + bidCalcs = new ArrayList(); + } + bidCalcs.add(bidCalc); + } + } + return bidCalcs; + } + + /** + * Inform the bidders of the allocated bids + */ + private void allocationPublication() { + this.printAllocations(); + for (BidCalculation bidCalc : this.bidCalcs) { + int entityID = bidCalc.getBidderID(); + Object data = null; + if (bidCalc.getBidderType() == DatacenterBrokerBid.class) { + data = createBidResult(bidCalc); + } else if (bidCalc.getBidderType() == DatacenterBid.class) { + data = createDatacenterBidResult(bidCalc); + } + sendNow(entityID, AuctionTags.ALLOCATION_PUBLICATION, data); + } + //TODO release this.bidCalcs in appropriate place + } + + private BidResult createBidResult(BidCalculation bidCalc) { + if (bidCalc.getBidderType() != DatacenterBrokerBid.class) { + throw new AuctionException("Incompatible bid"); + } + + Map> assignments = null; + Set vms = bidCalc.getAllocatedVMs(); + if (vms != null) { + for (Vm vm : vms) { + Map datacenters = null; + Set datacenterBids = this.allocations.getAllocatedDatacenterBids(vm); + if (datacenterBids != null) { + for (BidCalculation datacenterBid : datacenterBids) { + VmAllocation vmAllocation = this.allocations.getVmAllocation(vm, datacenterBid); + if (datacenters == null) { //Initialization + datacenters = new HashMap(); + } + datacenters.put(datacenterBid.getBidderID(), vmAllocation); + } + } + + if (datacenters != null) { + if (assignments == null) { //Initialization + assignments = new HashMap>(); + } + assignments.put(vm, datacenters); + } + } + } + + BidResult bidResult = new BidResult(bidCalc.getCalculatedPrice(), assignments); + return bidResult; + } + + private Map> createDatacenterBidResult(BidCalculation bidCalc) { + if (bidCalc.getBidderType() != DatacenterBid.class) { + throw new AuctionException("Incompatible bid"); + } + + Map> assignments = null; + + Set offeredVMs = bidCalc.getAllocatedVMs(); + if (offeredVMs != null) { + for (Vm offeredVM : offeredVMs) { + List requestedVMs = this.allocations.getRequestAllocations(bidCalc, offeredVM); + + if (requestedVMs != null) { + if (assignments == null) { //Initialization + assignments = new HashMap> (); + } + if (!assignments.containsKey(offeredVM)) { + assignments.put((DatacenterAbstractVm)offeredVM, null); + } + List vmAllocations = assignments.get(offeredVM); + if (vmAllocations == null) { + vmAllocations = new ArrayList(); + assignments.put((DatacenterAbstractVm)offeredVM, vmAllocations); + } + + vmAllocations.addAll(requestedVMs); + } + } + } + return assignments; + } + + private void printAllocations() { + Log.printLine(); + Log.printLine("#######Auctioneer Allocation Publication#######"); + + List brokerBidCalcs = getBidCalcs(this.bidCalcs, DatacenterBrokerBid.class); + + if (brokerBidCalcs != null) { + Log.printLine("Broker(ID)\tVM\tDatacenter(ID)\tAmount\tCost(per unit)"); + + for (BidCalculation bidCalc : brokerBidCalcs) { + Log.printLine("--------------------------------------------------------------"); + BidResult bidResult = createBidResult(bidCalc); + Map> allocs = bidResult.getVMAllocations(); + + Log.printLine(CloudSim.getEntity(bidCalc.getBidderID()).getName() + "(" + bidCalc.getBidderID() + ")");/*bidCalc.getBidderID())*/; + if (allocs != null) { + for (Vm vm : allocs.keySet()) { + Map datacenterIDs = allocs.get(vm); + if (datacenterIDs != null) { + for (Integer datacenterID : datacenterIDs.keySet()) { + VmAllocation vmAllocation = datacenterIDs.get(datacenterID); + Log.printLine("\t\t" + ((Vm)vm).getId() + "\t" + + CloudSim.getEntityName(datacenterID) + "(" + datacenterID + ")" + "\t " + + vmAllocation.getAllocatedAmount() + "\t" + vmAllocation.getAllocationPrice()); + } + } + } + } else { + Log.printLine("\t\t\tNO ALLOCATION"); + } + Log.printLine(); + } + } + + Log.printLine("#######Auctioneer Allocation Publication#######"); + Log.printLine(); + } + + private void printBidCalcs(String name, List brokerBidCalcs) { + System.out.println("Printing the bid calculations for " + name); + for (BidCalculation calc : brokerBidCalcs) { + System.out.println(calc.toString() + ", norm=" + calc.getNorm()); + } + System.out.println("Finished printing the bid calculations for " + name); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AverageBidComparator.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AverageBidComparator.java new file mode 100644 index 000000000..9c515991f --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/AverageBidComparator.java @@ -0,0 +1,24 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +import org.cloudbus.cloudsim.auction.AuctionException; + +import java.util.Comparator; + +public class AverageBidComparator implements Comparator { + + @Override + public int compare(BidCalculation o1, BidCalculation bc) { + if (o1.getBidderType() != bc.getBidderType()) { + throw new AuctionException("Incompatible types to be ordered."); + } + + int returnValue = 0; + if (o1.getAverageBid() < bc.getAverageBid()) { + returnValue = -1; + } else if (o1.getAverageBid() > bc.getAverageBid()) { + returnValue = 1; + } + return returnValue * (o1.isBidAscOrder()?1:-1); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/BidCalculation.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/BidCalculation.java new file mode 100644 index 000000000..9ef31ca55 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/BidCalculation.java @@ -0,0 +1,205 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +import org.cloudbus.cloudsim.Vm; +import org.cloudbus.cloudsim.auction.bid.Bid; +import org.cloudbus.cloudsim.auction.vm.VmUtils; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Contains the calculation data for a Bid that is hidden from bidder view + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/17 + */ +class BidCalculation implements Comparable { + + /** + * The primary requested/offered bid + * Contains the bundle of resources and their relative amount that are requested/offered. + * Contains the requested/offered price for resources + */ + private Bid bid; + + /** + * The final assignments + * Contains the bundle of resources and their relative amount that are assigned. + * Contains the calculated price for assigned resources + */ + private Bid assignedBid; + + /** + * The density by which the ordering of Bids is decided + */ + private Double norm; + + /** + * Used to cache ordered resources. + * The resources in each bid must be ordered. + * This flag tells if the ordering is done on the bid or not, to avoid multiple orderings. + * TODO: caching is not implemented yet + */ + //private boolean isBidOrdered; + + public BidCalculation(Bid bid) { + this.bid = bid; + } + + public void subtractCalculatedPrice(double price) { + this.assignedBid.setPrice(this.assignedBid.getPrice() - price); + } + + public double getCalculatedPrice() { + if (this.assignedBid != null) { + return this.assignedBid.getPrice(); + } + return 0; + } + + /** + * Called when a datacenter can offer some/all requested amount for a + * requested VM amount by a broker + * @param vm {@link Vm} + * @param assignedAmount The amount of allocated VMs + * @param price The price which must be get/paid for the assigned VM + */ + void assignAllocation(Vm vm, int assignedAmount, double price) { + if (this.assignedBid == null) { + this.assignedBid = new Bid(this.bid.getBidderID()) { + + // Though the following override is not necessary + @Override + public boolean isAscOrder() { + return false; + } + }; + } + + if (this.assignedBid.containsVM(vm)) { // update if exists from before + this.assignedBid.updateVM(vm, assignedAmount + this.assignedBid.getQuantity(vm)); + } else { // create new if doesn't exist from before + this.assignedBid.addVM(vm, assignedAmount); + } + + this.assignedBid.addPrice(price); + } + + /** + * Called when a datacenter can offer some/all requested amount for a + * requested VM amount by a broker + * @param vm {@link Vm} + * @param subtractAmount The amount of allocated VMs + * @param subtractPrice The price which must be get/paid for the assigned VM + */ + void releaseAllocation(Vm vm, int subtractAmount, double subtractPrice) { + if (this.assignedBid != null && this.assignedBid.containsVM(vm)) { + this.assignedBid.updateVM(vm, this.assignedBid.getQuantity(vm) - subtractAmount); + this.subtractCalculatedPrice(subtractPrice); + } + } + + public List getOrderedResources() { + return this.bid.getOrderedResources(); + } + + int getRemainingQuantity(Vm vm) { + int totalQuantity = this.bid.getQuantity(vm); + /** + * If some amount is previously assigned + */ + if (this.assignedBid != null && + this.assignedBid.containsVM(vm)){ + totalQuantity = totalQuantity - this.assignedBid.getQuantity(vm); + } + return totalQuantity; + } + + public Class getBidderType() { + return this.bid.getClass(); + } + + public int getBidderID() { + return this.bid.getBidderID(); + } + + /** + * Returns the density by which the ordering of Bids is decided :D + * TODO: Null checks are not handled in this method to detect the problems in code. + */ + public double getNorm() { + if (this.norm == null) { + Map bundle = this.bid.getResourceBundle(); + if (bundle != null) { + double totalWeight = 0; + for (Vm vm : bundle.keySet()) { + int amount = bundle.get(vm); + totalWeight += VmUtils.getTotalWeight(vm, amount); + } + this.norm = (this.bid.getPrice() / Math.sqrt(totalWeight)) * this.bid.getPriority(); + } + } + + return this.norm; + } + + /** + * @return the average bid or unit price that a bidder has assigned for its resources + */ + public double getAverageBid() { + return this.bid.getPrice() / this.bid.getTotalQuantity(); + } + + /** + * @return true if all the requests/offers of the bidder are assigned, false if did not. + */ + public boolean isSatisfied() { + if (this.bid != null) { + Set primaryVms = this.bid.getResources(); + if (primaryVms != null) { + for (Vm vm : primaryVms) { + if (this.getRemainingQuantity(vm) != 0) { + return false; + } + } // end of for (Vm primaryVm : primaryVms) + } // end of if (primaryVms != null) + } // end of if (this.bid != null) + + return true; + } + + public Set getAllocatedVMs() { + if (this.assignedBid != null) { + return this.assignedBid.getResources(); + } + return null; + } + + public boolean containsVm(Vm vm) { + if (this.bid != null && this.bid.containsVM(vm)) { + return true; + } + return false; + } + + public boolean isBidAscOrder() { + return this.bid.isAscOrder(); + } + + //Default comparator for BidCalculation + private Comparator normComparator = new NormComparator(); + + @Override + public int compareTo(BidCalculation bc) { + return this.normComparator.compare(this, bc); + } + + @Override + public String toString() { + return this.bid.toString(); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/BidResult.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/BidResult.java new file mode 100644 index 000000000..16d621821 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/BidResult.java @@ -0,0 +1,51 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +import org.cloudbus.cloudsim.Vm; + +import java.util.Map; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents the result of a bid from bidder. + * This result is sent to bidders after auction runs the algorithm. + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/22 + */ +public class BidResult { + + private double calculatedPrice; + /** + * Key in first map represents the requested VM by broker + * Key in second map is the datacenter's ID which is going to serve the request + * Value in second map is the amount that the datacenter can offer for requested VM + */ + private Map> allocations; + + public double getCalculatedPrice() { + return calculatedPrice; + } + + public BidResult(double calculatedPrice, Map> allocations) { + this.calculatedPrice = calculatedPrice; + this.allocations = allocations; + } + + public boolean isWinner() { + return this.allocations != null; + } + + /** + * Key in first map represents the requested VM by broker + * Key in second map is the datacenter's ID which is going to serve the request + * Value in second map is the amount and price that the datacenter can offer for requested VM + * + * @return Map> + */ + public Map> getVMAllocations() { + return allocations; + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/NormComparator.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/NormComparator.java new file mode 100644 index 000000000..e8afeb1fb --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/NormComparator.java @@ -0,0 +1,27 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +import org.cloudbus.cloudsim.auction.AuctionException; + +import java.util.Comparator; + +/** + * Default comparator for BidCalculation + */ +public class NormComparator implements Comparator { + + @Override + public int compare(BidCalculation bc1, BidCalculation bc2) { + if (bc1.getBidderType() != bc2.getBidderType()) { + throw new AuctionException("Incompatible types to be ordered."); + } + + int returnValue = 0; + if (bc1.getNorm() < bc2.getNorm()) { + returnValue = -1; + } else if (bc1.getNorm() > bc2.getNorm()) { + returnValue = 1; + } + return returnValue * (bc1.isBidAscOrder()?1:-1); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/VmAllocation.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/VmAllocation.java new file mode 100644 index 000000000..542d10ff1 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/auctioneer/VmAllocation.java @@ -0,0 +1,37 @@ +package org.cloudbus.cloudsim.auction.auctioneer; + +import org.cloudbus.cloudsim.Vm; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Contains the amount of allocation for a VM + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/24 + */ +public class VmAllocation { + private Vm vm; + private int allocatedAmount; + private double allocationPrice; + + public VmAllocation(Vm vm, int allocatedAmount, double allocationPrice) { + this.vm = vm; + this.allocatedAmount = allocatedAmount; + this.allocationPrice = allocationPrice; + } + + public Vm getVm() { + return vm; + } + + public int getAllocatedAmount() { + return allocatedAmount; + } + + public double getAllocationPrice() { + return allocationPrice; + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/Bid.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/Bid.java new file mode 100644 index 000000000..cf5cda361 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/Bid.java @@ -0,0 +1,146 @@ +package org.cloudbus.cloudsim.auction.bid; + +import org.cloudbus.cloudsim.Vm; +import org.cloudbus.cloudsim.auction.vm.VmComparator; +import org.cloudbus.cloudsim.core.CloudSim; + +import java.util.*; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents a bid from datacenter or a broker + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/7/16 + */ +public abstract class Bid { + + private final int bidderID; + + /** + * Represents a bundle of resources and their relative offered/requested quantity that + * is bid by a Datacenter/Broker + */ + private Map resourceBundle; + + private double price; + + /** + * Getter & setters + */ + + public int getBidderID() { + return bidderID; + } + + public Map getResourceBundle() { + return resourceBundle; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public void addPrice(double price) { + this.price += price; + } + + /* + * Constructors + */ + public Bid(int bidderID) { + this(bidderID, 0); + } + + public Bid(int bidderID, double price) { + super(); + this.bidderID = bidderID; + this.price = price; + } + + /** + * Adds VM to resource bundle + * @param vm Vm + * @param quantity + */ + public void addVM(Vm vm, int quantity) { + if (this.resourceBundle == null) { + this.resourceBundle = new HashMap(); + } + this.updateVM(vm, quantity); + } + + /** + *Updates the VM in resource bundle + * @param vm Vm + * @param quantity + */ + public void updateVM(Vm vm, int quantity) { + this.resourceBundle.put(vm, quantity); + } + + public boolean containsVM(Vm vm) { + boolean vmExists = false; + if (this.resourceBundle != null) { + return this.resourceBundle.containsKey(vm); + } + return vmExists; + } + + public Set getResources() { + return this.resourceBundle.keySet(); + } + + /** + * TODO: The overhead of this method is big. Since this method is + * called many times, the result can be cached locally. + * @return List the ordered VMs in a bundle. + */ + public List getOrderedResources() { + List orderedList = (new ArrayList(this.getResources())); + Collections.sort(orderedList, new VmComparator()); + return orderedList; + } + + public Integer getQuantity(Vm vm) { + return this.resourceBundle.get(vm); + } + + /** + *TODO: null checks aren't handled + * @return The total amount of bids + */ + public int getTotalQuantity() { + int totalAmount = 0; + Collection amounts = this.resourceBundle.values(); + for (int amount : amounts) { + totalAmount += amount; + } + return totalAmount; + } + + /** + * Decides if ordering in VM Allocation Based on + * Combinatorial Double Auction is ascending/descending + * @return boolean true if ascending, false if descending + */ + public abstract boolean isAscOrder(); + + @Override + public String toString() { + return "Bidder" + CloudSim.getEntityName(this.bidderID) + " price: " + this.getPrice(); + } + + /** + * @return The priority of the bid + */ + public long getPriority() { + return 1; + } +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/ContainerVMBid.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/ContainerVMBid.java new file mode 100644 index 000000000..75cf7338c --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/ContainerVMBid.java @@ -0,0 +1,28 @@ +package org.cloudbus.cloudsim.auction.bid; + +/** + * Represents a bid from a Container VM + * @author henri.vandenbulk + */ +public class ContainerVMBid extends Bid { + + /** + * The duration for which the resource is needed + */ + private long duration; + + public ContainerVMBid(int containerVMID, double price, long duration) { + super(containerVMID, price); + this.duration = duration; + } + + @Override + public boolean isAscOrder() { + return false; + } + + @Override + public long getPriority() { + return this.duration; + } +} diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/DatacenterBid.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/DatacenterBid.java new file mode 100644 index 000000000..d689adbd7 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/DatacenterBid.java @@ -0,0 +1,41 @@ +package org.cloudbus.cloudsim.auction.bid; + +import org.cloudbus.cloudsim.Vm; +import org.cloudbus.cloudsim.auction.AuctionException; +import org.cloudbus.cloudsim.auction.vm.DatacenterAbstractVm; + +/** + * Represents a bid from a datacenter + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/16 + */ +public class DatacenterBid extends Bid { + + public DatacenterBid(int datacenterID) { + super(datacenterID); + } + + public DatacenterBid(int datacenterID, long price) { + super(datacenterID, price); + } + + @Override + public void addVM(Vm vm, int quantity) { + if (vm instanceof DatacenterAbstractVm) { + DatacenterAbstractVm dvm = ((DatacenterAbstractVm) vm); + super.addVM(vm, quantity); + this.addPrice(dvm.getTotalCostPerMI() * quantity); + } else { + throw new AuctionException("The offerd vm in datacenter bid must be of type DatacenterAbstractVm."); + } + } + + @Override + public boolean isAscOrder() { + return true; + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/DatacenterBrokerBid.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/DatacenterBrokerBid.java new file mode 100644 index 000000000..514550086 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bid/DatacenterBrokerBid.java @@ -0,0 +1,33 @@ +package org.cloudbus.cloudsim.auction.bid; + +/** + * Represents a bid from a broker + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/16 + * Updated on 2013/2/14 + */ +public class DatacenterBrokerBid extends Bid { + + /** + * The duration for which the resource is needed + */ + private long duration; + + public DatacenterBrokerBid(int brokerID, double price, long duration) { + super(brokerID, price); + this.duration = duration; + } + + @Override + public boolean isAscOrder() { + return false; + } + + @Override + public long getPriority() { + return this.duration; + } +} diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/AuctionAgent.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/AuctionAgent.java new file mode 100644 index 000000000..33651d5a7 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/AuctionAgent.java @@ -0,0 +1,108 @@ +package org.cloudbus.cloudsim.auction.bidder; + +import org.cloudbus.cloudsim.auction.auctioneer.AuctionTags; +import org.cloudbus.cloudsim.auction.bid.Bid; +import org.cloudbus.cloudsim.core.SimEvent; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Each bidder has an AuctionAgent to defer the responsibilities of handling + * auction events to it. + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/20 + */ +public class AuctionAgent { + /** + * The owner of this auction-agent + */ + private Bidder bidder; + + /** + * The auction bidder's bid + */ + private Bid bid; + + /** + * The activity (open/close) of auctioneer entity + */ + public boolean auctionOpen; + + /** + * Denotes if the bid is accepted by Auctioneer or not + */ + public boolean bidAccepted; + + + /** + * Getters & Setters method + */ + public Bid getBid() { + return this.bid; + } + + public void setBid(Bid bid) { + this.bid = bid; + } + + private boolean isAuctionOpen() { + return auctionOpen; + } + + /** + * Constructor + * @param bidder Bidder + */ + public AuctionAgent(Bidder bidder) { + this.bidder = bidder; + } + + /** + * Process the Auction event + * + * @param ev SimEvent + * @return true if the event is an auction event (this means it is processed) + */ + protected boolean processAuctionEvent(SimEvent ev) { + switch (ev.getTag()){ + /** + * The following cases are related to Auction notion + */ + case AuctionTags.AUCTION_START: + this.processAuctionOpened(); + break; + case AuctionTags.BID_ACKNOWLEDGE: + this.processBidAcknowledgment((Boolean) ev.getData()); + break; + case AuctionTags.AUCTION_CLOSE: + this.processAuctionClosed(); + break; + case AuctionTags.ALLOCATION_PUBLICATION: + this.bidder.processAllocations(ev); + break; + default: + return false; + } + return true; + } + + private void processAuctionOpened() { + this.auctionOpen = true; + this.bidder.bidAuction(); + } + + private void processBidAcknowledgment(Boolean flag) { + this.bidAccepted = flag; + } + + private void processAuctionClosed() { + this.auctionOpen = false; + } + + public boolean isReadyToBid() { + return this.isAuctionOpen() && this.bid != null; + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/Bidder.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/Bidder.java new file mode 100644 index 000000000..d3672cad2 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/Bidder.java @@ -0,0 +1,20 @@ +package org.cloudbus.cloudsim.auction.bidder; + +import org.cloudbus.cloudsim.core.SimEvent; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents an entity which wants to bid to an auction. + * The entity must have an AuctonAgent by which the following methods are called. + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/20 + */ +public interface Bidder { + + public void bidAuction(); + + public void processAllocations(SimEvent ev); +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderContainerVM.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderContainerVM.java new file mode 100644 index 000000000..3cd910b90 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderContainerVM.java @@ -0,0 +1,198 @@ +package org.cloudbus.cloudsim.auction.bidder; + +import org.cloudbus.cloudsim.DatacenterBroker; +import org.cloudbus.cloudsim.Log; +import org.cloudbus.cloudsim.Vm; +import org.cloudbus.cloudsim.auction.auctioneer.AuctionTags; +import org.cloudbus.cloudsim.auction.auctioneer.Auctioneer; +import org.cloudbus.cloudsim.auction.auctioneer.BidResult; +import org.cloudbus.cloudsim.auction.auctioneer.VmAllocation; +import org.cloudbus.cloudsim.auction.bid.Bid; +import org.cloudbus.cloudsim.auction.bid.ContainerVMBid; +import org.cloudbus.cloudsim.auction.bid.DatacenterBrokerBid; +import org.cloudbus.cloudsim.auction.vm.ClonedVm; +import org.cloudbus.cloudsim.container.containerProvisioners.ContainerBwProvisioner; +import org.cloudbus.cloudsim.container.containerProvisioners.ContainerPe; +import org.cloudbus.cloudsim.container.containerProvisioners.ContainerRamProvisioner; +import org.cloudbus.cloudsim.container.core.ContainerVm; +import org.cloudbus.cloudsim.container.core.PowerContainerVm; +import org.cloudbus.cloudsim.container.schedulers.ContainerScheduler; +import org.cloudbus.cloudsim.core.CloudSim; +import org.cloudbus.cloudsim.core.CloudSimTags; +import org.cloudbus.cloudsim.core.SimEvent; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Represents a Container VM that can bid on an auction + * + * @author henri.vandenbulk + */ +public class BidderContainerVM extends PowerContainerVm implements Bidder { + + private AuctionAgent auctionAgent; + + public BidderContainerVM(int id, int userId, double mips, float ram, long bw, long size, String vmm, ContainerScheduler containerScheduler, ContainerRamProvisioner containerRamProvisioner, ContainerBwProvisioner containerBwProvisioner, List peList, double schedulingInterval) { + super(id, userId, mips, ram, bw, size, vmm, containerScheduler, containerRamProvisioner, containerBwProvisioner, peList, schedulingInterval); + this.auctionAgent = new AuctionAgent(this); + } + +// public BidderContainerVM(String name) throws Exception { +// super(name); +// this.auctionAgent = new AuctionAgent(this); +// } + +// @Override +// protected void processOtherEvent(SimEvent ev) { +// if (!this.auctionAgent.processAuctionEvent(ev)) { +// super.processOtherEvent(ev); +// } +// } +// +// @Override +// public void startEntity() { +// Log.printLine(this.getId() + " is starting and registering to bid..."); +// sendNow(Auctioneer.getAuctioneerEntityId(), AuctionTags.REGISTER_BIDDER, getId()); +// } + + @Override + public void bidAuction() { + if (this.auctionAgent.isReadyToBid()) { +// sendNow(Auctioneer.getAuctioneerEntityId(), AuctionTags.BID_AUCTION, +// this.auctionAgent.getBid()); + } + } + + /* + When asked to bid on an auction return the bid + */ + public double bidOnAuction(double mips, double mem) { +// if (this.auctionAgent.isReadyToBid()) { +// return this.auctionAgent.getBid(); +// } +// else return null; + + return computeScore(mips, mem); + } + + /* + * Compute the score which will be the bid. + */ + public double computeScore(double mips, double mem) { + double fractionUsedContainers = 0; + double fractionUsedMemory = 1.0 - mem / this.getRam(); + double fractionUsedMips = 1.0 - mips / this.getTotalMips(); + int n = this.getNumberOfContainers(); + if (n != 0) { + fractionUsedContainers = 1.0 - 1 / this.getNumberOfContainers(); + } + return (fractionUsedMemory + fractionUsedMips + fractionUsedContainers) / 3.0; + } + + /** + * Null checks aren't handled in this method to help debugging the + * probable logical problems. + * + * @param ev SimEvent + */ + @Override + public void processAllocations(SimEvent ev) { + + } +// @Override +// public void processAllocations(SimEvent ev) { +// BidResult bidResult = (BidResult) ev.getData(); +// if (bidResult.isWinner()) {//this.getId() +// //get the list of VMs and the amounts to be created +// Map> vmAllocations = bidResult.getVMAllocations(); +// +// if (vmAllocations != null) { +// Set Vms = vmAllocations.keySet(); +// for (Vm vm : Vms) { +// if (vm.getClass() == Vm.class) { +// Map datacenterRation = vmAllocations.get(vm); +// if (datacenterRation != null) { +// Set datacenterIDs = datacenterRation.keySet(); +// +// Vm clonedVm = vm; +// +// Iterator datacenterIDsIterator = datacenterIDs.iterator(); +// for (int i = 0; i < datacenterIDs.size(); i++) { +// /** +// * A more than one datacenters have offered VMs therefore we +// * clone VM to create a new VM and request it +// */ +// if (i > 0) { +// clonedVm = new ClonedVm(vm); +// } +// +// int datacenterID = datacenterIDsIterator.next(); +// VmAllocation vmAllocation = datacenterRation.get(datacenterID); +// int allocatedAmount = vmAllocation.getAllocatedAmount(); +// for (int j = 0; j < allocatedAmount; j++) { +// /** +// * A datacenter has offered more than one VM therefore we +// * clone VM to create a new VM and request it +// */ +// if (j > 0) { +// clonedVm = new ClonedVm(vm); +// } +// /** +// * Add the VM to submit list. For more information look at information on +// * this.submitVmList method. +// */ +// getVmList().add(clonedVm); +// +// /** +// * Create the VM on specified datacenter. +// */ +// this.createVmInDatacenter(datacenterID, clonedVm); +// } +// } +// } +// } +// } +// } +// } +// } + + /** + * Creates the Container in VM + * + * @param datacenterId Id of the chosen PowerDatacenter + * @param vm Vm that is going to be created on Datacenter + */ +// protected void createContainerInVM(int datacenterId, Vm vm) { +// if (!getVmsToDatacentersMap().containsKey(vm.getId())) { //Youness: Find VMs that are not previously assigned to a Datacenter +// String datacenterName = CloudSim.getEntityName(datacenterId); +// Log.printLine(CloudSim.clock() + ": " + getName() + ": Trying to Create VM #" + vm.getUid() + " in " + datacenterName); +// sendNow(datacenterId, CloudSimTags.VM_CREATE_ACK, vm); +// setVmsRequested(getVmsRequested()+1); +// } +// getDatacenterRequestedIdsList().add(datacenterId); +// +// /** +// * TODO:VM acks are not handled in this method and this might +// * be a threat when calling this method directly +// */ +// +// } + public void submitBid(ContainerVMBid bid) { + this.auctionAgent.setBid(bid); + } + + /** + * The submit action is done when the auctioneer acknowledges the broker to + * create a VM on a specified datacenter. This action is done in processAllocations method. + * Specifying the submitted VMs is because when a Datacenter acknowledges to Broker that + * a VM is created, Broker can lookup it up in its submitted VMs to take proper action. This is + * done in processVmCreate method of DatacenterBroker. + */ + @Deprecated + public void submitVmList(List list) { + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderDatacenter.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderDatacenter.java new file mode 100644 index 000000000..10b54438a --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderDatacenter.java @@ -0,0 +1,187 @@ +package org.cloudbus.cloudsim.auction.bidder; + +import org.cloudbus.cloudsim.*; +import org.cloudbus.cloudsim.auction.auctioneer.AuctionTags; +import org.cloudbus.cloudsim.auction.auctioneer.Auctioneer; +import org.cloudbus.cloudsim.auction.auctioneer.VmAllocation; +import org.cloudbus.cloudsim.auction.bid.DatacenterBid; +import org.cloudbus.cloudsim.auction.vm.ClonedVm; +import org.cloudbus.cloudsim.auction.vm.DatacenterAbstractVm; +import org.cloudbus.cloudsim.auction.vm.VmCharacteristics; +import org.cloudbus.cloudsim.core.CloudSimTags; +import org.cloudbus.cloudsim.core.SimEvent; + +import java.util.List; +import java.util.Map; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents a datacenter that can bid some offers in an auction + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/28 + */ +public class BidderDatacenter extends Datacenter implements Bidder{ + private AuctionAgent auctionAgent; + + public BidderDatacenter(String name, + DatacenterCharacteristics characteristics, + VmAllocationPolicy vmAllocationPolicy, List storageList, + double schedulingInterval) throws Exception { + super(name, characteristics, vmAllocationPolicy, storageList, + schedulingInterval); + this.auctionAgent = new AuctionAgent(this); + } + + @Override + protected void processOtherEvent(SimEvent ev) { + if (!this.auctionAgent.processAuctionEvent(ev)) { + super.processOtherEvent(ev); + } + } + + @Override + public void startEntity() { + super.startEntity(); + sendNow(Auctioneer.getAuctioneerEntityId(), AuctionTags.REGISTER_BIDDER, getId()); + } + + @Override + public void bidAuction() { + if (this.auctionAgent.isReadyToBid()) { + sendNow(Auctioneer.getAuctioneerEntityId(), AuctionTags.BID_AUCTION, + this.auctionAgent.getBid()); + } + } + + public void submitBid(DatacenterBid bid) { + this.auctionAgent.setBid(bid); + } + + /** + * The method is overrided to calculate the MIPs debt based on auction algorithm price + */ + @Override + protected void checkCloudletCompletion() { + List list = getVmAllocationPolicy().getHostList(); + for (int i = 0; i < list.size(); i++) { + Host host = list.get(i); + for (Vm vm : host.getVmList()) { + while (vm.getCloudletScheduler().isFinishedCloudlets()){ + Cloudlet cl = vm.getCloudletScheduler().getNextFinishedCloudlet(); + // TODO: Not sure how this is used yet. +// calcMIPSDebt(vm, cl); + if (cl != null) { + Log.printLine("cloudlet_" + cl.getCloudletId() + " finished and will be returned."); + sendNow(cl.getUserId(), CloudSimTags.CLOUDLET_RETURN, cl); + } + } + } + } + } + + /** + * The OfferedVMs and list of their assigned requested VMs (bundled with + * requested VMs' relative requested amount and auctioned price). + */ + private Map> assignments = null; + + @SuppressWarnings("unchecked") + @Override + public void processAllocations(SimEvent ev) { + this.assignments = (Map>) ev.getData(); + } + + private void calcMIPSDebt(Vm vm, Cloudlet cl) { + double amount = 0.0; +// if (getDebts().containsKey(cl.getUserId())) { +// amount = getDebts().get(cl.getUserId()); +// } + + for (DatacenterAbstractVm datacenterAbstractVm : this.assignments.keySet()) { + for (VmAllocation vmAllocation : this.assignments.get(datacenterAbstractVm)) { + if (vmAllocation.getVm() == vm) { + amount += vmAllocation.getAllocationPrice() * cl.getCloudletLength(); +// getDebts().put(vm.getUserId(), amount); + break; + } + } + } + } + + /** + * Service the VM if it is allocated by Auction + */ + @Override + protected void processVmCreate(SimEvent ev, boolean ack) { + Vm vm = (Vm) ev.getData(); + + DatacenterAbstractVm datacenterAbstractVm = getAllocatedDatacenterVM(vm); + if (datacenterAbstractVm != null) { + //A trick to calculate costs based on VM characteristics not the Datacenter characteristics + VmCharacteristics vmCharacteristics = datacenterAbstractVm.getVmCharacteristics(); + getCharacteristics().setCostPerMem(vmCharacteristics.getCostPerMem()); + getCharacteristics().setCostPerStorage(vmCharacteristics.getCostPerStorage()); + super.processVmCreate(ev, ack); + } + } + + @Override + protected void processCloudletSubmit(SimEvent ev, boolean ack) { + Cloudlet cl = (Cloudlet) ev.getData(); + int userId = cl.getUserId(); + int vmId = cl.getVmId(); + Host host = getVmAllocationPolicy().getHost(vmId, userId); + Vm vm = host.getVm(vmId, userId); + + DatacenterAbstractVm datacenterAbstractVm = getAllocatedDatacenterVM(vm); + if (datacenterAbstractVm != null) { + //A trick to calculate costs based on VM characteristics not the Datacenter characteristics + VmCharacteristics vmCharacteristics = datacenterAbstractVm.getVmCharacteristics(); + getCharacteristics().setCostPerBw(vmCharacteristics.getCostPerBw()); + super.processCloudletSubmit(ev, ack); + } + } + + /** + * Returns the datacenter abstract VM that is allocated for parameter VM + * + * @param vm Vm + * @return DatacenterAbstractVm + */ + private DatacenterAbstractVm getAllocatedDatacenterVM(Vm vm) { + Vm parameterVM; + if (vm instanceof ClonedVm) { //If more than one VM of the same type requested + parameterVM = ((ClonedVm)vm).getBaseVM(); + } else { + parameterVM = vm; + } + + for (DatacenterAbstractVm datacenterAbstractVm : this.assignments.keySet()) { + for (VmAllocation vmAllocation : this.assignments.get(datacenterAbstractVm)) { + if (vmAllocation.getVm() == parameterVM) { + return datacenterAbstractVm; + } + } + } + return null; + } + + public void printDebts() { + Log.printLine("*****BidderDatacenter: "+this.getName()+"*****"); + Log.printLine("Broker ID\t\tDebt"); + +// Set keys = getDebts().keySet(); +// Iterator iter = keys.iterator(); +// DecimalFormat df = new DecimalFormat("#.##"); +// while (iter.hasNext()) { +// int key = iter.next(); +// double value = getDebts().get(key); +// Log.printLine(key+"\t\t"+df.format(value)); +// } + Log.printLine("**********************************"); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderDatacenterBroker.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderDatacenterBroker.java new file mode 100644 index 000000000..f3d15f8f9 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/bidder/BidderDatacenterBroker.java @@ -0,0 +1,158 @@ +package org.cloudbus.cloudsim.auction.bidder; + +import org.cloudbus.cloudsim.DatacenterBroker; +import org.cloudbus.cloudsim.Log; +import org.cloudbus.cloudsim.Vm; +import org.cloudbus.cloudsim.auction.auctioneer.AuctionTags; +import org.cloudbus.cloudsim.auction.auctioneer.Auctioneer; +import org.cloudbus.cloudsim.auction.auctioneer.BidResult; +import org.cloudbus.cloudsim.auction.auctioneer.VmAllocation; +import org.cloudbus.cloudsim.auction.bid.DatacenterBrokerBid; +import org.cloudbus.cloudsim.auction.vm.ClonedVm; +import org.cloudbus.cloudsim.core.CloudSim; +import org.cloudbus.cloudsim.core.CloudSimTags; +import org.cloudbus.cloudsim.core.SimEvent; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Represents a Broker which can bid into Auction + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/20 + */ +public class BidderDatacenterBroker extends DatacenterBroker implements Bidder{ + + private AuctionAgent auctionAgent; + public BidderDatacenterBroker(String name) throws Exception { + super(name); + this.auctionAgent = new AuctionAgent(this); + } + + @Override + protected void processOtherEvent(SimEvent ev) { + if (!this.auctionAgent.processAuctionEvent(ev)) { + super.processOtherEvent(ev); + } + } + + @Override + public void startEntity() { + Log.printLine(getName() + " is starting registering to bid..."); + sendNow(Auctioneer.getAuctioneerEntityId(), AuctionTags.REGISTER_BIDDER, getId()); + } + + @Override + public void bidAuction() { + if (this.auctionAgent.isReadyToBid()) { + sendNow(Auctioneer.getAuctioneerEntityId(), AuctionTags.BID_AUCTION, + this.auctionAgent.getBid()); + } + } + + /** + * Null checks aren't handled in this method to help debugging the + * probable logical problems. + * @param ev SimEvent + */ + @Override + public void processAllocations(SimEvent ev) { + BidResult bidResult = (BidResult) ev.getData(); + if (bidResult.isWinner()) {//this.getId() + //get the list of VMs and the amounts to be created + Map> vmAllocations = bidResult.getVMAllocations(); + + if (vmAllocations != null) { + Set Vms = vmAllocations.keySet(); + for (Vm vm : Vms) { + if (vm.getClass() == Vm.class) { + Map datacenterRation = vmAllocations.get(vm); + if (datacenterRation != null) { + Set datacenterIDs = datacenterRation.keySet(); + + Vm clonedVm = vm; + + Iterator datacenterIDsIterator = datacenterIDs.iterator(); + for (int i = 0; i < datacenterIDs.size(); i++) { + /** + * A more than one datacenters have offered VMs therefore we + * clone VM to create a new VM and request it + */ + if (i > 0) { + clonedVm = new ClonedVm(vm); + } + + int datacenterID = datacenterIDsIterator.next(); + VmAllocation vmAllocation = datacenterRation.get(datacenterID); + int allocatedAmount = vmAllocation.getAllocatedAmount(); + for (int j = 0; j < allocatedAmount; j++) { + /** + * A datacenter has offered more than one VM therefore we + * clone VM to create a new VM and request it + */ + if (j > 0) { + clonedVm = new ClonedVm(vm); + } + /** + * Add the VM to submit list. For more information look at information on + * this.submitVmList method. + */ + getVmList().add(clonedVm); + + /** + * Create the VM on specified datacenter. + */ + this.createVmInDatacenter(datacenterID, clonedVm); + } + } + } + } + } + } + } + } + + /** + * Creates the Vm in Datacenter + * + * @param datacenterId Id of the chosen PowerDatacenter + * @param vm Vm that is going to be created on Datacenter + */ + protected void createVmInDatacenter(int datacenterId, Vm vm) { + if (!getVmsToDatacentersMap().containsKey(vm.getId())) { //Youness: Find VMs that are not previously assigned to a Datacenter + String datacenterName = CloudSim.getEntityName(datacenterId); + Log.printLine(CloudSim.clock() + ": " + getName() + ": Trying to Create VM #" + vm.getUid() + " in " + datacenterName); + sendNow(datacenterId, CloudSimTags.VM_CREATE_ACK, vm); + setVmsRequested(getVmsRequested()+1); + } + getDatacenterRequestedIdsList().add(datacenterId); + + /** + * TODO:VM acks are not handled in this method and this might + * be a threat when calling this method directly + */ + + } + + + public void submitBid(DatacenterBrokerBid bid) { + this.auctionAgent.setBid(bid); + } + + /** + * The submit action is done when the auctioneer acknowledges the broker to + * create a VM on a specified datacenter. This action is done in processAllocations method. + * Specifying the submitted VMs is because when a Datacenter acknowledges to Broker that + * a VM is created, Broker can lookup it up in its submitted VMs to take proper action. This is + * done in processVmCreate method of DatacenterBroker. + */ + @Deprecated + public void submitVmList(List list) { + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/ClonedVm.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/ClonedVm.java new file mode 100644 index 000000000..bcd07d302 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/ClonedVm.java @@ -0,0 +1,53 @@ +package org.cloudbus.cloudsim.auction.vm; + +import org.cloudbus.cloudsim.CloudletScheduler; +import org.cloudbus.cloudsim.Vm; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Represents a VM that is cloned from a base VM because the requested quantity + * for base VM was more than one + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/9/16 + */ +public class ClonedVm extends Vm { + private static int ID_COUNTER = -1; + /** + * The parent VM for this fake VM + */ + private Vm baseVM; + + public static int getID() { + ID_COUNTER++; + return ID_COUNTER; + } + + public Vm getBaseVM() { + return this.baseVM; + } + + @SuppressWarnings("unchecked") + public ClonedVm(Vm vm) { + super(ClonedVm.getID(), vm.getUserId(), vm.getMips(), vm.getNumberOfPes(), + vm.getRam(), vm.getBw(), vm.getSize(), vm.getVmm(), vm.getCloudletScheduler()); + this.baseVM = vm; + + /** + * Create a new cloudlet scheduler based on baseVM type + */ + Class clazz = (Class) vm.getCloudletScheduler().getClass(); + CloudletScheduler cloudletScheduler = null; + try { + cloudletScheduler = clazz.newInstance(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + this.setCloudletScheduler(cloudletScheduler); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/DatacenterAbstractVm.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/DatacenterAbstractVm.java new file mode 100644 index 000000000..ef99adcc3 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/DatacenterAbstractVm.java @@ -0,0 +1,38 @@ +package org.cloudbus.cloudsim.auction.vm; + +import org.cloudbus.cloudsim.Vm; + +/** + * Represents the abstract VM that is offered by a Datacenter + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/25 + * */ +public class DatacenterAbstractVm extends Vm { + + private VmCharacteristics vmCharacteristics; + + public DatacenterAbstractVm(double mips, int pesNumber, int ram, long bw, + long size, VmCharacteristics vmCharacteristics) { + super(-1, -1, mips, pesNumber, ram, bw, size, vmCharacteristics.getVmm(), null); + this.setVmCharacteristics(vmCharacteristics); + } + + private void setVmCharacteristics(VmCharacteristics vmCharacteristics) { + this.vmCharacteristics = vmCharacteristics; + } + + public VmCharacteristics getVmCharacteristics() { + return vmCharacteristics; + } + + /*TODO I doubt if I should multiply pes number as following or not. The mechanism + * may be changed by cloudlet scheduling policy. + * */ + public double getTotalCostPerMI() { + return this.getVmCharacteristics().getCostPerSecond() / this.getMips() * this.getNumberOfPes(); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmCharacteristics.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmCharacteristics.java new file mode 100644 index 000000000..d1ac18bbc --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmCharacteristics.java @@ -0,0 +1,22 @@ +package org.cloudbus.cloudsim.auction.vm; + +import org.cloudbus.cloudsim.auction.EntityCharacteristics; + +/** + * Represents the characteristics of a VM + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/25 + */ +public class VmCharacteristics extends EntityCharacteristics { + + public VmCharacteristics(String architecture, String os, String vmm, + double timeZone, double costPerSec, + double costPerMem, double costPerBw, double costPerStorage) { + super(architecture, os, vmm, timeZone, costPerSec, costPerMem, costPerBw, + costPerStorage); + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmComparator.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmComparator.java new file mode 100644 index 000000000..34a40dd80 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmComparator.java @@ -0,0 +1,29 @@ +package org.cloudbus.cloudsim.auction.vm; + +import org.cloudbus.cloudsim.Vm; + +import java.util.Comparator; + +/** + * Used to compare VMs based on their weight to each other + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/8/27 + */ +public class VmComparator implements Comparator { + + @Override + public int compare(Vm o1, Vm o2) { + double m = VmUtils.getWeight(o1); + double n = VmUtils.getWeight(o2); + if (m < n) { + return -1; + } else if (m > n) { + return 1; + } + return 0; + } + +} \ No newline at end of file diff --git a/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmUtils.java b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmUtils.java new file mode 100644 index 000000000..288daa366 --- /dev/null +++ b/modules/cloudsim/src/main/java/org.cloudbus.cloudsim.auction/vm/VmUtils.java @@ -0,0 +1,46 @@ +package org.cloudbus.cloudsim.auction.vm; + +import org.cloudbus.cloudsim.Vm; + +/** + * VM Allocation Based on Combinatorial Double Auction + * Provides some utilities for auction based calculations + * + * @author Youness Teimoury + * Blog: http://youness-teimoury.blogspot.com/ + * Email: youness126@gmail.com + * Created on 2011/9/16 + */ +public class VmUtils { + /** + * The policy by which we calculate the weight of the vm in VM Allocation Based + * on Combinatorial Double Auction + * Moreover, by this criteria, the VMs are ordered ascendingly in a bundle. + */ + public static double getWeight(Vm vm) { + return vm.getMips() * vm.getNumberOfPes(); + } + + /** + * The policy by which we calculate the weight of the vm in VM Allocation Based + * on Combinatorial Double Auction + * @param amount The amount of vm instances + */ + public static double getTotalWeight(Vm vm, int amount) { + return VmUtils.getWeight(vm) * amount; + } + + /** + * Checks if the offeredVm can satisfy the requestedVm's needs or not * + * @param offeredVM Vm + * @param requestedVM Vm + * @return boolean + */ + public static boolean canServe(Vm offeredVM, Vm requestedVM) { + return VmUtils.getWeight(requestedVM) <= VmUtils.getWeight(offeredVM) && + requestedVM.getRam() <= offeredVM.getRam() && + requestedVM.getSize() <= offeredVM.getSize() && + requestedVM.getBw() <= offeredVM.getBw(); + } + +} diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/CloudletSchedulerDynamicWorkload.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/CloudletSchedulerDynamicWorkload.java index 5418385ff..488a35589 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/CloudletSchedulerDynamicWorkload.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/CloudletSchedulerDynamicWorkload.java @@ -55,6 +55,12 @@ public class CloudletSchedulerDynamicWorkload extends CloudletSchedulerTimeShare */ private List cacheCurrentRequestedMips; + public CloudletSchedulerDynamicWorkload() { + super(); + mips = 0; + numberOfPes = 0; + } + /** * Instantiates a new VM scheduler * diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicy.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicy.java index fcf982bb9..653c8c45d 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicy.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicy.java @@ -15,6 +15,7 @@ public abstract class ContainerPlacementPolicy { * Gets the VM List, and the excluded VMs * * @param vmList the host + * @param obj the Container * @return the destination vm to place container */ public abstract ContainerVm getContainerVm(List vmList, Object obj, Set excludedVmList); diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyAuction.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyAuction.java new file mode 100644 index 000000000..87c8bf25e --- /dev/null +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyAuction.java @@ -0,0 +1,55 @@ +package org.cloudbus.cloudsim.container.containerPlacementPolicies; + +import org.cloudbus.cloudsim.Log; +import org.cloudbus.cloudsim.auction.bidder.BidderContainerVM; +import org.cloudbus.cloudsim.container.core.Container; +import org.cloudbus.cloudsim.container.core.ContainerVm; +import org.cloudbus.cloudsim.container.utils.RandomGen; + +import java.util.List; +import java.util.Set; + +/** + * @author henri.vandenbulk + * For container placement based on performing an action. + */ +public class ContainerPlacementPolicyAuction extends ContainerPlacementPolicy { + @Override + public ContainerVm getContainerVm(List vmList, Object obj, Set excludedVmList) { + ContainerVm containerVm = null; + + ContainerVm selectedVm = null; + Container container = (Container)obj; + double lowestBid = Double.MAX_VALUE; + double bid = 0; + + // Look at what's requested + //double totalMips = containerVm1.getMips(); + double totalMips = container.getCurrentRequestedTotalMips(); + double totalMemory = container.getCurrentRequestedRam(); + + for (ContainerVm containerVm1 : vmList) { + if (excludedVmList.contains(containerVm1)) { + continue; + } + + // Ask the VM to bid + if (containerVm1 instanceof BidderContainerVM) { + bid = ((BidderContainerVM) containerVm1).bidOnAuction(totalMips, totalMemory); + } + + + Log.formatLine(container.getId() + " -> " + containerVm1.getId() + " :" + + "Auction, bid %.2f, total request %.2f millicores %.2f memory bytes", + bid, totalMips, totalMemory); + + // Select the VM with the max score + if (Double.compax re(lowestBid, bid) > 0) { + lowestBid = bid; + selectedVm = containerVm1; + } + } + return selectedVm; + + } +} diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyBalanced.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyBalanced.java new file mode 100644 index 000000000..81af185f0 --- /dev/null +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyBalanced.java @@ -0,0 +1,80 @@ +package org.cloudbus.cloudsim.container.containerPlacementPolicies; + +import org.cloudbus.cloudsim.Log; +import org.cloudbus.cloudsim.container.core.Container; +import org.cloudbus.cloudsim.container.core.ContainerVm; + +import java.util.List; +import java.util.Set; + +/** + * Created by hvandenb + * BalancedResourceAllocation favors nodes with balanced resource usage rate. + * BalancedResourceAllocation should **NOT** be used alone, and **MUST** be used together with LeastRequestedPriority. + * It calculates the difference between the cpu and memory fracion of capacity, and prioritizes the host based on how + * close the two metrics are to each other. + * Detail: score = 10 - abs(cpuFraction-memoryFraction)*10. The algorithm is partly inspired by: + * "Wei Huang et al. An Energy Efficient Virtual Machine Placement Algorithm with Balanced Resource Utilization" + */ +public class ContainerPlacementPolicyBalanced extends ContainerPlacementPolicy { + + @Override + public ContainerVm getContainerVm(List vmList, Object obj, Set excludedVmList) { + ContainerVm selectedVm = null; + Container container = (Container)obj; + int maxScore = 0; + + // Look at what's requested + //double totalMips = containerVm1.getMips(); + double totalMips = container.getCurrentRequestedTotalMips(); +// double totalMemory = containerVm1.getRam(); + double totalMemory = container.getCurrentRequestedRam(); + + for (ContainerVm containerVm1 : vmList) { + if (excludedVmList.contains(containerVm1)) { + continue; + } + + // Check Capacity + double allocatableResourceMips = containerVm1.getAvailableMips(); +// double allocatableResourceMemory = containerVm1.getRam() - containerVm1.getCurrentAllocatedRam(); + double allocatableResourceMemory = containerVm1.getContainerRamProvisioner().getAvailableVmRam(); + + + double cpuFraction = fractionOfCapacity(totalMips, allocatableResourceMips); + double memoryFraction = fractionOfCapacity(totalMemory, allocatableResourceMemory); + int score = 0; + if (cpuFraction >= 1 || memoryFraction >= 1) { + // if requested >= capacity, the corresponding host should never be preferred. + score = 0; + } else { + // Upper and lower boundary of difference between cpuFraction and memoryFraction are -1 and 1 + // respectively. Multilying the absolute value of the difference by 10 scales the value to + // 0-10 with 0 representing well balanced allocation and 10 poorly balanced. Subtracting it from + // 10 leads to the score which also scales from 0 to 10 while 10 representing well balanced. + double diff = Math.abs(cpuFraction - memoryFraction); + score = (int)(10 - diff*10); + } + + Log.formatLine(container.getId() + " -> " + containerVm1.getId() + " :" + + "Balanced Resource Allocation, capacity %.2f millicores %.2f memory bytes, total request %.2f millicores %.2f memory bytes, score %d", + allocatableResourceMips, allocatableResourceMemory, + totalMips, totalMemory,score); + + // Select the VM with the max score + if ( score > maxScore) { + maxScore = score; + selectedVm = containerVm1; + } + } + + return selectedVm; + } + + private double fractionOfCapacity(double requested, double capacity) { + if (capacity == 0) { + return 1; + } + return (requested) / (capacity); + } +} diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyLeastFull.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyLeastFull.java index 2d6f7a3f6..b1e3848fd 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyLeastFull.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyLeastFull.java @@ -19,7 +19,7 @@ public ContainerVm getContainerVm(List vmList, Object obj, Set vmList, Object obj, Set excludedVmList) { + ContainerVm selectedVm = null; + Container container = (Container)obj; + int minScore = Integer.MAX_VALUE; + + // Look at what's requested + //double totalMips = containerVm1.getMips(); + double totalMips = container.getCurrentRequestedTotalMips(); +// double totalMemory = containerVm1.getRam(); + double totalMemory = container.getCurrentRequestedRam(); + + for (ContainerVm containerVm1 : vmList) { + if (excludedVmList.contains(containerVm1)) { + continue; + } + + // Check Capacity + double allocatableResourceMips = containerVm1.getAvailableMips(); +// double allocatableResourceMemory = containerVm1.getRam() - containerVm1.getCurrentAllocatedRam(); + double allocatableResourceMemory = containerVm1.getContainerRamProvisioner().getAvailableVmRam(); + + + double cpuScore = calculateUnusedScore(totalMips, allocatableResourceMips, Integer.toString(containerVm1.getId())); + double memoryScore = calculateUnusedScore(totalMemory, allocatableResourceMemory, Integer.toString(containerVm1.getId())); + int score = 0; + score = (int)(cpuScore + memoryScore) / 2; + + Log.formatLine(container.getId() + " -> " + containerVm1.getId() + " :" + + "Least Requested Priority, capacity %.2f millicores %.2f memory bytes, total request %.2f millicores %.2f memory bytes, score %.2f CPU %.2f memory", + allocatableResourceMips, allocatableResourceMemory, + totalMips, totalMemory, cpuScore, memoryScore); + + // Select the VM with the max score + if ( score < minScore) { + minScore = score; + selectedVm = containerVm1; + } + } + + return selectedVm; + } + + private double calculateUnusedScore(double requested, double capacity, String vm) { + if (capacity == 0) { + return 0; + } + if (requested > capacity) { + Log.formatLine("Combined requested resources %.2f from existing VM exceeds capacity %.2f on node %s", + requested, capacity, vm); + + return 0; + } + return ((capacity - requested) * 10) / capacity; + } + +} diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyMostFull.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyMostFull.java index 72d4cd7e4..5fff3d51a 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyMostFull.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerPlacementPolicies/ContainerPlacementPolicyMostFull.java @@ -21,7 +21,7 @@ public ContainerVm getContainerVm(List vmList, Object obj, Set maxMips) { maxMips = containerUsage; selectedVm = containerVm1; diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerProvisioners/ContainerPe.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerProvisioners/ContainerPe.java index cfa75f607..a8ddb4a5d 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerProvisioners/ContainerPe.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/containerProvisioners/ContainerPe.java @@ -37,7 +37,7 @@ public class ContainerPe { private int status; /** - * The pe provisioner. + * The Processing Element (PE) a.k.a. CPU provisioner. */ private ContainerPeProvisioner containerPeProvisioner; diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/ContainerVm.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/ContainerVm.java index cea6c28c3..be7a1d265 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/ContainerVm.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/ContainerVm.java @@ -67,7 +67,7 @@ public class ContainerVm { /** - * The vmm. + * The Virtual Machine Manager (vmm). */ private String vmm; @@ -143,7 +143,7 @@ public class ContainerVm { private ContainerBwProvisioner containerBwProvisioner; /** - * The vm list. + * The container list. */ private final List containerList = new ArrayList<>(); @@ -846,9 +846,10 @@ public void reallocateMigratingInContainers() { */ public boolean isSuitableForContainer(Container container) { - return (getContainerScheduler().getPeCapacity() >= container.getCurrentRequestedMaxMips()&& getContainerScheduler().getAvailableMips() >= container.getWorkloadTotalMips() - && getContainerRamProvisioner().isSuitableForContainer(container, container.getCurrentRequestedRam()) && getContainerBwProvisioner() - .isSuitableForContainer(container, container.getCurrentRequestedBw())); + return (getContainerScheduler().getPeCapacity() >= container.getCurrentRequestedMaxMips() && + getContainerScheduler().getAvailableMips() >= container.getWorkloadTotalMips() && + getContainerRamProvisioner().isSuitableForContainer(container, container.getCurrentRequestedRam()) && + getContainerBwProvisioner().isSuitableForContainer(container, container.getCurrentRequestedBw())); } /** @@ -1226,7 +1227,7 @@ public boolean containerCreate(Container container) { public int getNumberOfContainers() { int c =0; for(Container container:getContainerList()){ - if(!getContainersMigratingIn().contains(container)){ + if(!getContainersMigratingIn().contains(container)){ c++; } } diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/PowerContainerDatacenterCM.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/PowerContainerDatacenterCM.java index d8192c5e7..c02762433 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/PowerContainerDatacenterCM.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/core/PowerContainerDatacenterCM.java @@ -326,6 +326,7 @@ public void setNewlyCreatedVmWriter(CostumeCSVWriter newlyCreatedVmWriter) { } public int getNewlyCreatedVms() { + newlyCreatedVms = newlyCreatedVmsList.size(); return newlyCreatedVms; } diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/hostSelectionPolicies/HostSelectionPolicy.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/hostSelectionPolicies/HostSelectionPolicy.java index 677cf0567..383c9620a 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/hostSelectionPolicies/HostSelectionPolicy.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/hostSelectionPolicies/HostSelectionPolicy.java @@ -7,6 +7,7 @@ /** * Created by sareh on 11/08/15. + * The host selection policy determines which hosts should be selected as the migration destination. */ public abstract class HostSelectionPolicy { diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/resourceAllocators/PowerContainerAllocationPolicy.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/resourceAllocators/PowerContainerAllocationPolicy.java index 229de761d..36e2c1b6f 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/resourceAllocators/PowerContainerAllocationPolicy.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/resourceAllocators/PowerContainerAllocationPolicy.java @@ -43,7 +43,7 @@ public boolean allocateVmForContainer(Container container, List con @Override public boolean allocateVmForContainer(Container container, ContainerVm containerVm) { if (containerVm == null) { - Log.formatLine("%.2f: No suitable VM found for Container#" + container.getId() + "\n", CloudSim.clock()); + Log.formatLine("%.2f: No suitable VM found for Container #" + container.getId() + "\n", CloudSim.clock()); return false; } if (containerVm.containerCreate(container)) { // if vm has been succesfully created in the host @@ -61,7 +61,7 @@ public boolean allocateVmForContainer(Container container, ContainerVm container } /** - * Find host for vm. + * Find vm for container. * * @param container the vm * @return the power host diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/vmSelectionPolicies/PowerContainerVmSelectionPolicy.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/vmSelectionPolicies/PowerContainerVmSelectionPolicy.java index 480a1ece0..c54cb8d41 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/vmSelectionPolicies/PowerContainerVmSelectionPolicy.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/container/vmSelectionPolicies/PowerContainerVmSelectionPolicy.java @@ -8,6 +8,8 @@ /** * Created by sareh on 28/07/15. + * The VM Selection Policy is used for selecting VMs to migrate when a host status is determined as + * "Overloaded" */ public abstract class PowerContainerVmSelectionPolicy { diff --git a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/core/CloudSim.java b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/core/CloudSim.java index 8f84897eb..43c940c04 100644 --- a/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/core/CloudSim.java +++ b/modules/cloudsim/src/main/java/org/cloudbus/cloudsim/core/CloudSim.java @@ -37,7 +37,7 @@ public class CloudSim { /** The Constant CLOUDSIM_VERSION_STRING. */ - private static final String CLOUDSIM_VERSION_STRING = "3.0"; + private static final String CLOUDSIM_VERSION_STRING = "4.0"; /** The id of CIS entity. */ private static int cisId = -1; @@ -345,7 +345,7 @@ public static List getCloudResourceList() { * start of the simulation. */ protected static void initialize() { - Log.printLine("Initialising..."); + Log.printLine("Initializing..."); entities = new ArrayList(); entitiesByName = new LinkedHashMap(); future = new FutureQueue(); diff --git a/modules/pom.xml b/modules/pom.xml index d2f84cb7a..d84779772 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -63,7 +63,11 @@ commons-math3 3.3 - + + commons-cli + commons-cli + 1.4 + diff --git a/run.sh b/run.sh new file mode 100755 index 000000000..aa6e16a9e --- /dev/null +++ b/run.sh @@ -0,0 +1,34 @@ +#!/bin/bash +JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home" +CLASS_PATH="/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home/lib/tools.jar:/Users/henri.vandenbulk/projects/cloudsim/modules/cloudsim-examples/target/classes:/Users/henri.vandenbulk/projects/cloudsim/modules/cloudsim/target/classes:/Users/henri.vandenbulk/.m2/repository/com/opencsv/opencsv/3.7/opencsv-3.7.jar:/Users/henri.vandenbulk/.m2/repository/org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar:/Users/henri.vandenbulk/.m2/repository/org/apache/commons/commons-math3/3.3/commons-math3-3.3.jar:/Users/henri.vandenbulk/.m2/repository/commons-cli/commons-cli/1.4/commons-cli-1.4.jar" + +# Variables +HOSTS="2 5 10" +CLOUDLETS="10 20 50 100 500 1000 2500 5000" +POLICY="MostFull FirstFit LeastFull Simple RandomSelection Balanced LeastRequested Auction" + +# +# What's the max allocation of containers to VMs? 25->2 +# +CSVCAT_HOME="~/tools" +RESULTS_HOME="/Users/henri.vandenbulk/projects/cloudsim/Results" +CURRENT_RUN=`date +%s` + +for host in $HOSTS +do + for vms in {5..20} + do + # echo $vms + for cloudlet in $CLOUDLETS + do + for cap in $POLICY + do + echo "hosts: " $host " VMs: " $vms " cloudlets: " $cloudlet " policy: " $cap + $JAVA_HOME/bin/java -classpath $CLASS_PATH org.cloudbus.cloudsim.examples.container.ContainerOverbooking --hosts $host --cloudlets $cloudlet --cap $cap --vms $vms -i 100 -r 1 + done + done + done +done + +# Combine all the results together +$CSVCAT_HOME/csvcat --skip-headers $RESULTS_HOME/stats/*.csv > $RESULTS_HOME/$CURRENT_RUN.csv