summaryrefslogtreecommitdiff
path: root/simulator
diff options
context:
space:
mode:
Diffstat (limited to 'simulator')
-rw-r--r--simulator/Dockerfile4
-rw-r--r--simulator/README.md34
-rw-r--r--simulator/build.gradle.kts6
-rw-r--r--simulator/buildSrc/build.gradle.kts4
-rw-r--r--simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts8
-rw-r--r--simulator/buildSrc/src/main/kotlin/library.kt2
-rw-r--r--simulator/gradle/wrapper/gradle-wrapper.jarbin58910 -> 59203 bytes
-rw-r--r--simulator/gradle/wrapper/gradle-wrapper.properties2
-rwxr-xr-xsimulator/gradlew2
-rw-r--r--simulator/gradlew.bat21
-rw-r--r--simulator/odcsim/README.md54
-rw-r--r--simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/Domain.kt54
-rw-r--r--simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationEngineProvider.kt35
-rw-r--r--simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt264
-rw-r--r--simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationAwareLoggerImpl.kt567
-rw-r--r--simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationIgnorantLoggerImpl.kt440
-rw-r--r--simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LoggerImpl.kt74
-rw-r--r--simulator/odcsim/odcsim-engine-omega/src/main/resources/META-INF/services/com.atlarge.odcsim.SimulationEngineProvider1
-rw-r--r--simulator/opendc-compute/build.gradle.kts (renamed from simulator/opendc/build.gradle.kts)6
-rw-r--r--simulator/opendc-compute/opendc-compute-core/build.gradle.kts (renamed from simulator/opendc/opendc-compute/build.gradle.kts)14
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/Flavor.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt)2
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/Server.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt)16
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/ServerEvent.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerEvent.kt)16
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/ServerState.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt)2
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/image/EmptyImage.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt)13
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/image/Image.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt)19
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/Metadata.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Metadata.kt)4
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/Node.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt)14
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/NodeEvent.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeEvent.kt)2
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/NodeState.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeState.kt)2
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/driver/BareMetalDriver.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt)22
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/service/ProvisioningService.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt)16
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/service/SimpleProvisioningService.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningService.kt)35
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/Hypervisor.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/Hypervisor.kt)10
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/HypervisorEvent.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorEvent.kt)10
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/InsufficientMemoryOnServerException.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/InsufficientMemoryOnServerException.kt)2
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/VirtDriver.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt)25
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/service/VirtProvisioningEvent.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningEvent.kt)4
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/service/VirtProvisioningService.kt (renamed from simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationEngine.kt)45
-rw-r--r--simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/workload/VmWorkload.kt47
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts (renamed from simulator/odcsim/odcsim-engine-omega/build.gradle.kts)23
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/ComputeSimExecutionContext.kt36
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/HypervisorView.kt37
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt246
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt206
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriverWorkload.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt)30
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt393
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimWorkloadImage.kt (renamed from simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngineProvider.kt)30
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AllocationPolicy.kt50
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AvailableCoreMemoryAllocationPolicy.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableCoreMemoryAllocationPolicy.kt)10
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AvailableMemoryAllocationPolicy.kt37
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ComparableAllocationPolicyLogic.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ComparableAllocationPolicyLogic.kt)19
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/NumberOfActiveServersAllocationPolicy.kt37
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ProvisionedCoresAllocationPolicy.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ProvisionedCoresAllocationPolicy.kt)10
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/RandomAllocationPolicy.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/RandomAllocationPolicy.kt)17
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ReplayAllocationPolicy.kt56
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/PowerModel.kt)2
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/power/PowerModels.kt)9
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/Powerable.kt)4
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimBareMetalDriverTest.kt (renamed from simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt)81
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimProvisioningServiceTest.kt (renamed from simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt)63
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimVirtDriverTest.kt145
-rw-r--r--simulator/opendc-core/build.gradle.kts (renamed from simulator/opendc/opendc-core/build.gradle.kts)9
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/Environment.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Environment.kt)8
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/Identity.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Identity.kt)14
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/Platform.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Platform.kt)10
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/User.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/User.kt)8
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/Zone.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Zone.kt)12
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/resource/Resource.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/Resource.kt)8
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/resource/TagContainer.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/TagContainer.kt)10
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceKey.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceKey.kt)14
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceRegistry.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistry.kt)6
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceRegistryImpl.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistryImpl.kt)9
-rw-r--r--simulator/opendc-core/src/main/kotlin/org/opendc/core/workload/Workload.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/workload/Workload.kt)14
-rw-r--r--simulator/opendc-experiments/build.gradle.kts (renamed from simulator/odcsim/build.gradle.kts)4
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc18/build.gradle.kts (renamed from simulator/opendc/opendc-experiments-sc18/build.gradle.kts)19
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/TestExperiment.kt (renamed from simulator/opendc/opendc-experiments-sc18/src/main/kotlin/com/atlarge/opendc/experiments/sc18/TestExperiment.kt)74
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc18/src/main/resources/env/setup-test.json (renamed from simulator/opendc/opendc-experiments-sc18/src/main/resources/env/setup-test.json)0
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/build.gradle.kts (renamed from simulator/opendc/opendc-experiments-sc20/build.gradle.kts)16
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/Main.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Main.kt)51
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Experiment.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Experiment.kt)32
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/ExperimentHelpers.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/ExperimentHelpers.kt)155
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Portfolio.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolio.kt)20
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Portfolios.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolios.kt)59
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Run.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Run.kt)63
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Scenario.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Scenario.kt)28
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/OperationalPhenomena.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/OperationalPhenomena.kt)2
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/Topology.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/Topology.kt)2
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/Workload.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/Workload.kt)16
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/monitor/ExperimentMonitor.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/monitor/ExperimentMonitor.kt)30
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/monitor/ParquetExperimentMonitor.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/monitor/ParquetExperimentMonitor.kt)26
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/reporter/ConsoleExperimentReporter.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/reporter/ConsoleExperimentReporter.kt)20
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ContainerExperimentDescriptor.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ContainerExperimentDescriptor.kt)10
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ExperimentDescriptor.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ExperimentDescriptor.kt)14
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ExperimentRunner.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ExperimentRunner.kt)12
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/TrialExperimentDescriptor.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/TrialExperimentDescriptor.kt)2
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionContext.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionContext.kt)2
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionListener.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionListener.kt)16
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionResult.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionResult.kt)2
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentScheduler.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentScheduler.kt)16
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ThreadPoolExperimentScheduler.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ThreadPoolExperimentScheduler.kt)19
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/internal/DefaultExperimentRunner.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/internal/DefaultExperimentRunner.kt)24
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/Event.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/Event.kt)4
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/HostEvent.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/HostEvent.kt)32
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/ProvisionerEvent.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/ProvisionerEvent.kt)18
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/RunEvent.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/RunEvent.kt)12
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/VmEvent.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/VmEvent.kt)28
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetEventWriter.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetEventWriter.kt)47
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetHostEventWriter.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetHostEventWriter.kt)18
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetProvisionerEventWriter.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetProvisionerEventWriter.kt)18
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt)18
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20ParquetTraceReader.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20ParquetTraceReader.kt)32
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20RawParquetTraceReader.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20RawParquetTraceReader.kt)45
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20StreamingParquetTraceReader.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20StreamingParquetTraceReader.kt)88
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20TraceConverter.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20TraceConverter.kt)82
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/WorkloadSampler.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/WorkloadSampler.kt)36
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/main/resources/log4j2.xml (renamed from simulator/opendc/opendc-experiments-sc20/src/main/resources/log4j2.xml)11
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/test/kotlin/org/opendc/experiments/sc20/Sc20IntegrationTest.kt (renamed from simulator/opendc/opendc-experiments-sc20/src/test/kotlin/com/atlarge/opendc/experiments/sc20/Sc20IntegrationTest.kt)111
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/env/single.txt (renamed from simulator/opendc/opendc-experiments-sc20/src/test/resources/env/single.txt)0
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/env/topology.txt (renamed from simulator/opendc/opendc-experiments-sc20/src/test/resources/env/topology.txt)0
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/trace/meta.parquet (renamed from simulator/opendc/opendc-experiments-sc20/src/test/resources/trace/meta.parquet)bin2148 -> 2148 bytes
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/trace/trace.parquet (renamed from simulator/opendc/opendc-experiments-sc20/src/test/resources/trace/trace.parquet)bin1672463 -> 1672463 bytes
-rw-r--r--simulator/opendc-format/build.gradle.kts (renamed from simulator/opendc/opendc-format/build.gradle.kts)23
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/EnvironmentReader.kt)17
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Model.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc18/Model.kt)24
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc18/Sc18EnvironmentReader.kt)54
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Model.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Model.kt)24
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt)70
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Sc20EnvironmentReader.kt)54
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/PerformanceInterferenceModelReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/PerformanceInterferenceModelReader.kt)12
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceEntry.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceEntry.kt)14
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceReader.kt)10
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceWriter.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceWriter.kt)8
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/VmPlacementReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/VmPlacementReader.kt)6
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/bitbrains/BitbrainsTraceReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/bitbrains/BitbrainsTraceReader.kt)65
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/gwf/GwfTraceReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/gwf/GwfTraceReader.kt)59
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/PerformanceInterferenceEntry.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/PerformanceInterferenceEntry.kt)2
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20PerformanceInterferenceReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20PerformanceInterferenceReader.kt)21
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20TraceReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20TraceReader.kt)51
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20VmPlacementReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20VmPlacementReader.kt)10
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/swf/SwfTraceReader.kt (renamed from simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/swf/SwfTraceReader.kt)87
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/wtf/WtfTraceReader.kt128
-rw-r--r--simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/swf/SwfTraceReaderTest.kt47
-rw-r--r--simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/wtf/WtfTraceReaderTest.kt46
-rw-r--r--simulator/opendc-format/src/test/resources/swf_trace.txt (renamed from simulator/opendc/opendc-format/src/test/resources/swf_trace.txt)0
-rw-r--r--simulator/opendc-format/src/test/resources/wtf-trace/tasks/schema-1.0/part.0.parquetbin0 -> 87475 bytes
-rw-r--r--simulator/opendc-runner-web/build.gradle.kts (renamed from simulator/opendc/opendc-runner-web/build.gradle.kts)17
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt (renamed from simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/Main.kt)91
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/ResultProcessor.kt (renamed from simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/ResultProcessor.kt)92
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/ScenarioManager.kt (renamed from simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/ScenarioManager.kt)38
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt (renamed from simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/TopologyParser.kt)79
-rw-r--r--simulator/opendc-runner-web/src/main/resources/log4j2.xml (renamed from simulator/opendc/opendc-runner-web/src/main/resources/log4j2.xml)9
-rw-r--r--simulator/opendc-simulator/build.gradle.kts0
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/build.gradle.kts (renamed from simulator/odcsim/odcsim-api/build.gradle.kts)11
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt281
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimExecutionContext.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt)38
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimHypervisor.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/SimpleVirtDriver.kt)430
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt48
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineModel.kt34
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/interference/PerformanceInterferenceModel.kt134
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MemoryUnit.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/MemoryUnit.kt)6
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/ProcessingNode.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingNode.kt)16
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/ProcessingUnit.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt)6
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkload.kt (renamed from simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt)30
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt (renamed from simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationContext.kt)54
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimWorkload.kt41
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimHypervisorTest.kt129
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt83
-rw-r--r--simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt (renamed from simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImageTest.kt)37
-rw-r--r--simulator/opendc-simulator/opendc-simulator-core/build.gradle.kts32
-rw-r--r--simulator/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/utils/DelayControllerClockAdapter.kt46
-rw-r--r--simulator/opendc-simulator/opendc-simulator-failures/build.gradle.kts31
-rw-r--r--simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/CorrelatedFaultInjector.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/CorrelatedFaultInjector.kt)25
-rw-r--r--simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/FailureDomain.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FailureDomain.kt)2
-rw-r--r--simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/FaultInjector.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FaultInjector.kt)6
-rw-r--r--simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/UncorrelatedFaultInjector.kt (renamed from simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/UncorrelatedFaultInjector.kt)21
-rw-r--r--simulator/opendc-utils/build.gradle.kts32
-rw-r--r--simulator/opendc-utils/src/main/kotlin/org/opendc/utils/flow/EventFlow.kt (renamed from simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/flow/EventFlow.kt)9
-rw-r--r--simulator/opendc-utils/src/main/kotlin/org/opendc/utils/flow/StateFlow.kt (renamed from simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/flow/StateFlow.kt)6
-rw-r--r--simulator/opendc-workflows/build.gradle.kts (renamed from simulator/opendc/opendc-workflows/build.gradle.kts)18
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/JobState.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/JobState.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerListener.kt37
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/StageWorkflowService.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowService.kt)86
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/TaskState.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/TaskState.kt)26
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/TaskStatus.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/TaskStatus.kt)2
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowEvent.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowEvent.kt)10
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowSchedulerMode.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowSchedulerMode.kt)29
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowService.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowService.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/StagePolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/StagePolicy.kt)12
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/DurationJobOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/DurationJobOrderPolicy.kt)22
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/JobAdmissionPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/JobAdmissionPolicy.kt)18
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/JobOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/JobOrderPolicy.kt)12
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/LimitJobAdmissionPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/LimitJobAdmissionPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/LoadJobAdmissionPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/LoadJobAdmissionPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/NullJobAdmissionPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/NullJobAdmissionPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/RandomJobOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/RandomJobOrderPolicy.kt)21
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/SizeJobOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/SizeJobOrderPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/SubmissionTimeJobOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/SubmissionTimeJobOrderPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/FirstFitResourceSelectionPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/FirstFitResourceSelectionPolicy.kt)17
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/FunctionalResourceFilterPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/FunctionalResourceFilterPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/RandomResourceSelectionPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/RandomResourceSelectionPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/ResourceFilterPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/ResourceFilterPolicy.kt)18
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/ResourceSelectionPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/ResourceSelectionPolicy.kt)12
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/ActiveTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/ActiveTaskOrderPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/BalancingTaskEligibilityPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/BalancingTaskEligibilityPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/CompletionTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/CompletionTaskOrderPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DependenciesTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DependenciesTaskOrderPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DependentsTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DependentsTaskOrderPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DurationHistoryTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DurationHistoryTaskOrderPolicy.kt)17
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DurationTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DurationTaskOrderPolicy.kt)22
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LimitPerJobTaskEligibilityPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LimitPerJobTaskEligibilityPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LimitTaskEligibilityPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LimitTaskEligibilityPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LoadTaskEligibilityPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LoadTaskEligibilityPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/NullTaskEligibilityPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/NullTaskEligibilityPolicy.kt)12
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/RandomTaskEligibilityPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/RandomTaskEligibilityPolicy.kt)16
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/RandomTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/RandomTaskOrderPolicy.kt)12
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/SubmissionTimeTaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/SubmissionTimeTaskOrderPolicy.kt)10
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/TaskEligibilityPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/TaskEligibilityPolicy.kt)14
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/TaskOrderPolicy.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/TaskOrderPolicy.kt)8
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Job.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Job.kt)18
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Metadata.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Metadata.kt)4
-rw-r--r--simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Task.kt (renamed from simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Task.kt)16
-rw-r--r--simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt (renamed from simulator/opendc/opendc-workflows/src/test/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt)58
-rw-r--r--simulator/opendc-workflows/src/test/resources/environment.json (renamed from simulator/opendc/opendc-workflows/src/test/resources/environment.json)0
-rw-r--r--simulator/opendc-workflows/src/test/resources/trace.gwf (renamed from simulator/opendc/opendc-workflows/src/test/resources/trace.gwf)0
-rw-r--r--simulator/opendc/README.md8
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt53
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt3
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt34
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt123
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt25
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt478
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt57
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt15
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt351
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt42
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt25
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt15
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt15
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt34
-rw-r--r--simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt167
-rw-r--r--simulator/opendc/opendc-format/src/test/kotlin/com/atlarge/opendc/format/trace/swf/SwfTraceReaderTest.kt23
-rw-r--r--simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowSchedulerListener.kt39
-rw-r--r--simulator/settings.gradle.kts25
244 files changed, 4650 insertions, 5322 deletions
diff --git a/simulator/Dockerfile b/simulator/Dockerfile
index e42c7f14..880af95d 100644
--- a/simulator/Dockerfile
+++ b/simulator/Dockerfile
@@ -23,9 +23,9 @@ RUN ./gradlew clean build --no-daemon > /dev/null 2>&1 || true
# Build project
COPY ./ /app/
-RUN ./gradlew --no-daemon :opendc:opendc-runner-web:installDist
+RUN ./gradlew --no-daemon :opendc-runner-web:installDist
FROM openjdk:14-slim
-COPY --from=builder /app/opendc/opendc-runner-web/build/install /app
+COPY --from=builder /app/opendc-runner-web/build/install /app
WORKDIR /app
CMD opendc-runner-web/bin/opendc-runner-web
diff --git a/simulator/README.md b/simulator/README.md
index 0e9a1671..61ef1d43 100644
--- a/simulator/README.md
+++ b/simulator/README.md
@@ -8,22 +8,34 @@
<p align="center">
Collaborative Datacenter Simulation and Exploration for Everybody
</p>
-<p align="center">
- <a href="https://travis-ci.org/atlarge-research/opendc-simulator">
- <img src="https://travis-ci.org/atlarge-research/opendc-simulator.svg?branch=master" alt="Build Status">
- </a>
+<p align="center">
<a href="https://opensource.org/licenses/MIT">
- <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="MIT License">
+ <img src="https://img.shields.io/badge/License-MIT-green.svg" alt="MIT License">
</a>
</p>
## Introduction
-This repository hosts the source code and development of the simulation component of the [OpenDC](https://opendc.org) project. This component is responsible for modelling and simulation of datacenters and their components. We have structured the repository into two individual subprojects:
-- **[odcsim](/odcsim)**
- A framework for discrete event simulation using the [Kotlin](https://kotlinlang.org/) language.
-- **[opendc](/opendc)**
- A collection of models for simulating clouds, datacenters and their components using the **odcsim** framework.
-
+This directory hosts the source code and development of the simulation component of the [OpenDC](https://opendc.org) project.
+This component is responsible for modelling and simulation of datacenters and their components. We have structured the directory into several subprojects:
+- **[opendc-core](opendc-core)**
+ This module establishes core concepts and terminology of datacenters that we share across the various modules.
+ Other `opendc` modules build on these concepts and extend it in various directions (e.g. virtual machines or workflows).
+- **[opendc-compute](opendc-compute)**
+ The [Infrastructure as a Service](https://en.wikipedia.org/wiki/Infrastructure_as_a_Service) (IaaS) component of OpenDC for computing infrastructure (similar to
+ [Amazon EC2](https://aws.amazon.com/ec2/) and [Google Compute Engine](https://cloud.google.com/compute)).
+- **[opendc-workflows](opendc-workflows)**
+ Workflow orchestration service built on top of OpenDC.
+- **[opendc-format](opendc-format)**
+ Collection of libraries for processing data formats related to (simulation of) cloud computing and datacenters.
+- **[opendc-experiments](opendc-experiments)**
+ Collection of experiments that use OpenDC to explore various concepts of cloud computing and datacenters.
+- **[opendc-runner-web](opendc-runner-web)**
+ Experiment runner that integrates with the OpenDC web interface.
+- **[opendc-simulator](opendc-simulator)**
+ Collection of libraries that enable simulation of various components of datacenters.
+- **[opendc-utils](opendc-utils)**
+ Collection of utilities that are shared across the OpenDC subprojects.
+
## Documentation
Check out the [Getting Started](#getting-started) section for a quick
overview.
diff --git a/simulator/build.gradle.kts b/simulator/build.gradle.kts
index 4775369b..b104654b 100644
--- a/simulator/build.gradle.kts
+++ b/simulator/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2017 atlarge-research
+ * Copyright (c) 2017 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,6 +25,6 @@ plugins {
}
allprojects {
- group = "com.atlarge.opendc"
+ group = "org.opendc"
version = "2.0.0"
}
diff --git a/simulator/buildSrc/build.gradle.kts b/simulator/buildSrc/build.gradle.kts
index 6ed95c71..7ccd920f 100644
--- a/simulator/buildSrc/build.gradle.kts
+++ b/simulator/buildSrc/build.gradle.kts
@@ -40,7 +40,7 @@ repositories {
}
dependencies {
- implementation(kotlin("gradle-plugin", version = "1.3.70"))
- implementation("org.jlleitschuh.gradle:ktlint-gradle:9.2.1")
+ implementation(kotlin("gradle-plugin", version = "1.4.10"))
+ implementation("org.jlleitschuh.gradle:ktlint-gradle:9.4.0")
implementation("org.jetbrains.dokka:dokka-gradle-plugin:0.10.1")
}
diff --git a/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts b/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts
index c0c37a09..452db573 100644
--- a/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts
+++ b/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts
@@ -40,6 +40,10 @@ java {
sourceCompatibility = JavaVersion.VERSION_1_8
}
+kotlin {
+ explicitApi()
+}
+
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
@@ -56,7 +60,3 @@ tasks.jacocoTestReport {
html.isEnabled = true
}
}
-
-dependencies {
- implementation(kotlin("stdlib"))
-}
diff --git a/simulator/buildSrc/src/main/kotlin/library.kt b/simulator/buildSrc/src/main/kotlin/library.kt
index 1a3c30a6..af278a07 100644
--- a/simulator/buildSrc/src/main/kotlin/library.kt
+++ b/simulator/buildSrc/src/main/kotlin/library.kt
@@ -45,5 +45,5 @@ object Library {
/**
* Kotlin coroutines support
*/
- val KOTLINX_COROUTINES = "1.3.7"
+ val KOTLINX_COROUTINES = "1.3.9"
}
diff --git a/simulator/gradle/wrapper/gradle-wrapper.jar b/simulator/gradle/wrapper/gradle-wrapper.jar
index 62d4c053..e708b1c0 100644
--- a/simulator/gradle/wrapper/gradle-wrapper.jar
+++ b/simulator/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/simulator/gradle/wrapper/gradle-wrapper.properties b/simulator/gradle/wrapper/gradle-wrapper.properties
index bb8b2fc2..12d38de6 100644
--- a/simulator/gradle/wrapper/gradle-wrapper.properties
+++ b/simulator/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/simulator/gradlew b/simulator/gradlew
index fbd7c515..4f906e0c 100755
--- a/simulator/gradlew
+++ b/simulator/gradlew
@@ -130,7 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
+
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
diff --git a/simulator/gradlew.bat b/simulator/gradlew.bat
index 5093609d..107acd32 100644
--- a/simulator/gradlew.bat
+++ b/simulator/gradlew.bat
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -64,21 +64,6 @@ echo location of your Java installation.
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
@@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/simulator/odcsim/README.md b/simulator/odcsim/README.md
deleted file mode 100644
index 78cfaa27..00000000
--- a/simulator/odcsim/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-<h1 align="center">
- <a href="http://opendc.org/">
- <img src="../misc/artwork/logo.png" width="100" alt="OpenDC">
- </a>
- <br>
- odcsim
-</h1>
-
-## Introduction
-**odcsim** is a framework for discrete event simulation in Kotlin, used
-by the [OpenDC](https://opendc.org) project.
-Projects are defined in terms of a hierarchical grouping of actors
-and the interactions between these actors
-([Actor model](https://en.wikipedia.org/wiki/Actor_model)).
-
-## Getting Started
-
-The instructions below are meant for when you would like to use `odcsim` separately from `opendc`. If you simply want to use the simulator, you do not need to follow them, please refer to the [main README](../README.md) for instructions.
-
-### Installation
-Please add the required packages as dependency in your project.
-Releases are available in the [Maven Central Repository](https://search.maven.org/).
-
-The package `odcsim-core` is required to construct a simulation model.
-A `odcsim-engine-*` package is needed for running the simulation
-model.
-
-#### Gradle
-Groovy
-```groovy
-implementation 'com.atlarge.odcsim:odcsim-api:2.0.0'
-runtime 'com.atlarge.odcsim:odcsim-engine-omega:2.0.0'
-```
-Kotlin
-```groovy
-implementation("com.atlarge.odcsim:odcsim-api:2.0.0")
-runtime("com.atlarge.odcsim:odcsim-engine-omega:2.0.0")
-```
-
-#### Maven
-```xml
-<dependency>
- <groupId>com.atlarge.odcsim</groupId>
- <artifactId>odcsim-api</artifactId>
- <version>2.0.0</version>
-</dependency>
-
-<dependency>
- <groupId>com.atlarge.odcsim</groupId>
- <artifactId>odcsim-engine-omega</artifactId>
- <version>2.0.0</version>
-</dependency>
-```
-
diff --git a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/Domain.kt b/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/Domain.kt
deleted file mode 100644
index c850952c..00000000
--- a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/Domain.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.odcsim
-
-import kotlinx.coroutines.CoroutineScope
-
-/**
- * An isolated execution unit that runs concurrently in simulation to the other simulation domains. A domain defines a
- * logical boundary between processes in simulation.
- */
-public interface Domain : CoroutineScope {
- /**
- * The name of this domain.
- */
- public val name: String
-
- /**
- * The parent domain to which the lifecycle of this domain is bound. In case this is a root domain, this refers to
- * itself.
- */
- public val parent: Domain
-
- /**
- * Construct an anonymous simulation sub-domain that is bound to the lifecycle of this domain.
- */
- public fun newDomain(): Domain
-
- /**
- * Construct a new simulation sub-domain with the specified [name].
- */
- public fun newDomain(name: String): Domain
-}
diff --git a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationEngineProvider.kt b/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationEngineProvider.kt
deleted file mode 100644
index a975fa3c..00000000
--- a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationEngineProvider.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2018 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.odcsim
-
-/**
- * A factory for [SimulationEngine] instances that allows users to dynamically load engine implementations.
- */
-public interface SimulationEngineProvider {
- /**
- * Construct an [SimulationEngine] with the given [name].
- */
- public operator fun invoke(name: String): SimulationEngine
-}
diff --git a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt b/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt
deleted file mode 100644
index e675b877..00000000
--- a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2018 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.odcsim.engine.omega
-
-import com.atlarge.odcsim.Domain
-import com.atlarge.odcsim.SimulationContext
-import com.atlarge.odcsim.SimulationEngine
-import com.atlarge.odcsim.engine.omega.logging.LoggerImpl
-import java.time.Clock
-import java.time.Instant
-import java.time.ZoneId
-import java.util.PriorityQueue
-import java.util.UUID
-import kotlin.coroutines.CoroutineContext
-import kotlin.coroutines.coroutineContext
-import kotlinx.coroutines.CancellableContinuation
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineExceptionHandler
-import kotlinx.coroutines.CoroutineName
-import kotlinx.coroutines.Delay
-import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.InternalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.Runnable
-import kotlinx.coroutines.SupervisorJob
-import org.jetbrains.annotations.Async
-import org.slf4j.Logger
-
-/**
- * The reference implementation of the [SimulationEngine] instance for the OpenDC simulation core.
- *
- * This engine implementation is a single-threaded implementation, running logical processes synchronously and
- * provides a single priority queue for all events (messages, ticks, etc) that occur.
- *
- * @param name The name of the engine instance.
- */
-public class OmegaSimulationEngine(override val name: String) : SimulationEngine {
- /**
- * The state of the actor system.
- */
- private var state: SimulationEngineState = SimulationEngineState.CREATED
-
- /**
- * The clock tracking the simulation time.
- */
- private val clock: VirtualClock = VirtualClock(0)
-
- /**
- * The event queue to process
- */
- private val queue: PriorityQueue<Event> = PriorityQueue(Comparator<Event> { lhs, rhs ->
- // Note that Comparator gives better performance than Comparable according to
- // profiling
- val cmp = lhs.time.compareTo(rhs.time)
- if (cmp == 0) lhs.id.compareTo(rhs.id) else cmp
- })
-
- /**
- * The active processes in the simulation engine.
- */
- private val registry: MutableMap<String, Domain> = HashMap()
-
- /**
- * A unique increasing identifier assigned to each event, needed because otherwise two events occurring in sequence
- * (but at the same time) may be differently ordered in the internal priority queue (queue) since it does not
- * guarantee insertion order.
- */
- private var nextId: Long = 0
-
- override fun newDomain(): Domain = newDomain(null)
-
- override fun newDomain(name: String): Domain = newDomain(name, null)
-
- override suspend fun run() {
- check(state != SimulationEngineState.TERMINATED) { "The simulation engine is terminated" }
-
- if (state == SimulationEngineState.CREATED) {
- state = SimulationEngineState.STARTED
- }
-
- val job = coroutineContext[Job]
-
- while (job?.isActive == true) {
- val event = queue.peek() ?: break
- val delivery = event.time
-
- // A message should never be delivered out of order in this single-threaded implementation. Assert for
- // sanity
- assert(delivery >= clock.time) { "Message delivered out of order [expected=$delivery, actual=${clock.time}]" }
-
- clock.time = delivery
- queue.poll()
-
- process(event)
- }
- }
-
- override suspend fun terminate() {
- state = SimulationEngineState.TERMINATED
- }
-
- /**
- * Schedule the specified event to be processed by the engine.
- */
- private fun schedule(@Async.Schedule event: Event) {
- assert(event.time >= clock.time) { "Message scheduled in the past [received=${event.time}, actual=${clock.time}]" }
- queue.add(event)
- }
-
- /**
- * Process the delivery of an event.
- */
- @OptIn(ExperimentalCoroutinesApi::class)
- private fun process(@Async.Execute event: Event) {
- // This has been inlined into this method for performance
- when (event) {
- is Event.Dispatch ->
- event.block.run()
- is Event.Resume ->
- with(event.continuation) { event.dispatcher.resumeUndispatched(Unit) }
- is Event.Timeout ->
- if (!event.isCancelled)
- event.block.run()
- }
- }
-
- /**
- * Spawn a new simulation domain.
- */
- private fun newDomainImpl(name: String, parent: DomainImpl?): Domain {
- val domain = DomainImpl(name, parent)
- require(domain.path !in registry) { "Domain name $name not unique" }
- registry[domain.path] = domain
- return domain
- }
-
- private fun newDomain(parent: DomainImpl?): Domain {
- val name = "$" + UUID.randomUUID()
- return newDomainImpl(name, parent)
- }
-
- private fun newDomain(name: String, parent: DomainImpl?): Domain {
- require(name.isNotEmpty()) { "Domain name may not be empty" }
- require(!name.startsWith("$")) { "Domain name may not start with $-sign" }
- require(!name.contains("/")) { "Domain name may not contain /" }
- return newDomainImpl(name, parent)
- }
-
- private inner class DomainImpl(override val name: String, parent: DomainImpl?) : SimulationContext, Domain {
- val job: Job = SupervisorJob(parent?.job)
- val path: String = (parent?.path ?: "") + "/$name"
-
- @InternalCoroutinesApi
- private val dispatcher = object : CoroutineDispatcher(), Delay {
- // CoroutineDispatcher
- override fun dispatch(context: CoroutineContext, block: Runnable) {
- schedule(Event.Dispatch(clock.time, nextId++, block))
- }
-
- // Delay
- override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
- schedule(Event.Resume(clock.time + timeMillis, nextId++, this, continuation))
- }
-
- override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
- val event = Event.Timeout(clock.time + timeMillis, nextId++, block)
- schedule(event)
- return event
- }
- }
-
- private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
- log.error("Uncaught exception", exception)
- }
-
- // SimulationContext
- override val key: CoroutineContext.Key<*> = SimulationContext.Key
-
- override val domain: Domain = this
-
- override val clock: VirtualClock
- get() = this@OmegaSimulationEngine.clock
-
- override val log: Logger by lazy(LazyThreadSafetyMode.NONE) { LoggerImpl.invoke(this) }
-
- override fun newDomain(): Domain = this@OmegaSimulationEngine.newDomain(this)
-
- override fun newDomain(name: String): Domain = this@OmegaSimulationEngine.newDomain(name, this)
-
- // Domain
- override val parent: Domain = parent ?: this
-
- @InternalCoroutinesApi
- override val coroutineContext: CoroutineContext = this + CoroutineName(name) + dispatcher + job + exceptionHandler
-
- override fun toString(): String = path
- }
-
- /**
- * Enumeration to track the state of the actor system.
- */
- private enum class SimulationEngineState {
- CREATED, STARTED, TERMINATED
- }
-
- /**
- * A wrapper around a message that has been scheduled for processing.
- *
- * @property time The point in time to deliver the message.
- */
- private sealed class Event(val time: Long, val id: Long) {
- class Dispatch(time: Long, id: Long, val block: Runnable) : Event(time, id) {
- override fun toString(): String = "Dispatch[$time]"
- }
-
- class Resume(time: Long, id: Long, val dispatcher: CoroutineDispatcher, val continuation: CancellableContinuation<Unit>) : Event(time, id) {
- override fun toString(): String = "Resume[$time]"
- }
-
- class Timeout(time: Long, id: Long, val block: Runnable, var isCancelled: Boolean = false) : Event(time, id), DisposableHandle {
- override fun dispose() {
- isCancelled = true
- }
-
- override fun toString(): String = "Timeout[$time]"
- }
- }
-
- /**
- * A virtual [Clock] implementation for keeping track of simulation time.
- */
- private data class VirtualClock(var time: Long) : Clock() {
- override fun withZone(zone: ZoneId?): Clock = throw NotImplementedError()
-
- override fun getZone(): ZoneId = ZoneId.systemDefault()
-
- override fun instant(): Instant = Instant.ofEpochMilli(time)
-
- override fun millis(): Long = time
- }
-}
diff --git a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationAwareLoggerImpl.kt b/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationAwareLoggerImpl.kt
deleted file mode 100644
index fca4826e..00000000
--- a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationAwareLoggerImpl.kt
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.odcsim.engine.omega.logging
-
-import com.atlarge.odcsim.SimulationContext
-import org.slf4j.Logger
-import org.slf4j.Marker
-import org.slf4j.helpers.MessageFormatter
-import org.slf4j.spi.LocationAwareLogger
-
-/**
- * An actor-specific [Logger] implementation that is aware of the calling location.
- *
- * @param ctx The owning [SimulationContext] of this logger.
- * @param delegate The [LocationAwareLogger] to delegate the messages to.
- */
-internal class LocationAwareLoggerImpl(
- ctx: SimulationContext,
- private val delegate: LocationAwareLogger
-) : LoggerImpl(ctx), Logger by delegate {
- /**
- * The fully qualified name of this class.
- */
- private val fqcn = LocationAwareLoggerImpl::class.java.name
-
- override fun trace(format: String?, arg: Any?) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(null, fqcn, LocationAwareLogger.TRACE_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun trace(format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(null, fqcn, LocationAwareLogger.TRACE_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun trace(format: String?, argArray: Array<Any?>) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(null, fqcn, LocationAwareLogger.TRACE_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun trace(msg: String?, t: Throwable?) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.TRACE_INT, msg, null, t)
- }
- }
-
- override fun trace(marker: Marker?, msg: String?) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.TRACE_INT, msg, null, null)
- }
- }
-
- override fun trace(marker: Marker?, format: String?, arg: Any?) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(marker, fqcn, LocationAwareLogger.TRACE_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun trace(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(marker, fqcn, LocationAwareLogger.TRACE_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun trace(marker: Marker?, format: String?, argArray: Array<Any?>) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(marker, fqcn, LocationAwareLogger.TRACE_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun trace(marker: Marker?, msg: String?, t: Throwable?) {
- if (!delegate.isTraceEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.TRACE_INT, msg, null, t)
- }
- }
-
- override fun debug(msg: String?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.DEBUG_INT, msg, null, null)
- }
- }
-
- override fun debug(format: String?, arg: Any?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(null, fqcn, LocationAwareLogger.DEBUG_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun debug(format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(null, fqcn, LocationAwareLogger.DEBUG_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun debug(format: String?, argArray: Array<Any?>) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- val ft = MessageFormatter.arrayFormat(format, argArray)
- delegate.log(null, fqcn, LocationAwareLogger.DEBUG_INT, ft.message, ft.argArray, ft.throwable)
- }
- }
-
- override fun debug(msg: String?, t: Throwable?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.DEBUG_INT, msg, null, t)
- }
- }
-
- override fun debug(marker: Marker?, msg: String?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.DEBUG_INT, msg, null, null)
- }
- }
-
- override fun debug(marker: Marker?, format: String?, arg: Any?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- val ft = MessageFormatter.format(format, arg)
- delegate.log(marker, fqcn, LocationAwareLogger.DEBUG_INT, ft.message, ft.argArray, ft.throwable)
- }
- }
-
- override fun debug(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(marker, fqcn, LocationAwareLogger.DEBUG_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun debug(marker: Marker?, format: String?, argArray: Array<Any?>) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- val ft = MessageFormatter.arrayFormat(format, argArray)
- delegate.log(marker, fqcn, LocationAwareLogger.DEBUG_INT, ft.message, argArray, ft.throwable)
- }
- }
-
- override fun debug(marker: Marker?, msg: String?, t: Throwable?) {
- if (!delegate.isDebugEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.DEBUG_INT, msg, null, t)
- }
- }
-
- override fun info(msg: String?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.INFO_INT, msg, null, null)
- }
- }
-
- override fun info(format: String?, arg: Any?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(null, fqcn, LocationAwareLogger.INFO_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun info(format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(null, fqcn, LocationAwareLogger.INFO_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun info(format: String?, argArray: Array<Any?>) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(null, fqcn, LocationAwareLogger.INFO_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun info(msg: String?, t: Throwable?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.INFO_INT, msg, null, t)
- }
- }
-
- override fun info(marker: Marker?, msg: String?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.INFO_INT, msg, null, null)
- }
- }
-
- override fun info(marker: Marker?, format: String?, arg: Any?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(marker, fqcn, LocationAwareLogger.INFO_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun info(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(marker, fqcn, LocationAwareLogger.INFO_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun info(marker: Marker?, format: String?, argArray: Array<Any?>) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(marker, fqcn, LocationAwareLogger.INFO_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun info(marker: Marker?, msg: String?, t: Throwable?) {
- if (!delegate.isInfoEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.INFO_INT, msg, null, t)
- }
- }
-
- override fun warn(msg: String?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.WARN_INT, msg, null, null)
- }
- }
-
- override fun warn(format: String?, arg: Any?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(null, fqcn, LocationAwareLogger.WARN_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun warn(format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(null, fqcn, LocationAwareLogger.WARN_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun warn(format: String?, argArray: Array<Any?>) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(null, fqcn, LocationAwareLogger.WARN_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun warn(msg: String?, t: Throwable?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.WARN_INT, msg, null, t)
- }
- }
-
- override fun warn(marker: Marker?, msg: String?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.WARN_INT, msg, null, null)
- }
- }
-
- override fun warn(marker: Marker?, format: String?, arg: Any?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(marker, fqcn, LocationAwareLogger.WARN_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun warn(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(marker, fqcn, LocationAwareLogger.WARN_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun warn(marker: Marker?, format: String?, argArray: Array<Any?>) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(marker, fqcn, LocationAwareLogger.WARN_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun warn(marker: Marker?, msg: String?, t: Throwable?) {
- if (!delegate.isWarnEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.WARN_INT, msg, null, t)
- }
- }
-
- override fun error(msg: String?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.ERROR_INT, msg, null, null)
- }
- }
-
- override fun error(format: String?, arg: Any?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(null, fqcn, LocationAwareLogger.ERROR_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun error(format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(null, fqcn, LocationAwareLogger.ERROR_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun error(format: String?, argArray: Array<Any?>) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(null, fqcn, LocationAwareLogger.ERROR_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun error(msg: String?, t: Throwable?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- delegate.log(null, fqcn, LocationAwareLogger.ERROR_INT, msg, null, t)
- }
- }
-
- override fun error(marker: Marker?, msg: String?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.ERROR_INT, msg, null, null)
- }
- }
-
- override fun error(marker: Marker?, format: String?, arg: Any?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg).message
- delegate.log(marker, fqcn, LocationAwareLogger.ERROR_INT, formattedMessage, arrayOf(arg), null)
- }
- }
-
- override fun error(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.format(format, arg1, arg2).message
- delegate.log(marker, fqcn, LocationAwareLogger.ERROR_INT, formattedMessage, arrayOf(arg1, arg2), null)
- }
- }
-
- override fun error(marker: Marker?, format: String?, argArray: Array<Any?>) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- val formattedMessage = MessageFormatter.arrayFormat(format, argArray).message
- delegate.log(marker, fqcn, LocationAwareLogger.ERROR_INT, formattedMessage, argArray, null)
- }
- }
-
- override fun error(marker: Marker?, msg: String?, t: Throwable?) {
- if (!delegate.isErrorEnabled) {
- return
- }
-
- withMdc {
- delegate.log(marker, fqcn, LocationAwareLogger.ERROR_INT, msg, null, t)
- }
- }
-}
diff --git a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationIgnorantLoggerImpl.kt b/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationIgnorantLoggerImpl.kt
deleted file mode 100644
index 856cecfa..00000000
--- a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LocationIgnorantLoggerImpl.kt
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.odcsim.engine.omega.logging
-
-import com.atlarge.odcsim.SimulationContext
-import org.slf4j.Logger
-import org.slf4j.Marker
-
-/**
- * A [Logger] implementation that is not aware of the calling location.
- *
- * @param ctx The owning [SimulationContext] of this logger.
- * @param delegate The [Logger] to delegate the messages to.
- */
-internal class LocationIgnorantLoggerImpl(
- ctx: SimulationContext,
- private val delegate: Logger
-) : LoggerImpl(ctx), Logger by delegate {
- override fun warn(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(marker, format, arg1, arg2) }
- }
-
- override fun warn(format: String?, arg1: Any?, arg2: Any?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(format, arg1, arg2) }
- }
-
- override fun warn(msg: String?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(msg) }
- }
-
- override fun warn(marker: Marker?, format: String?, arg: Any?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(marker, format, arg) }
- }
-
- override fun warn(marker: Marker?, format: String?, vararg arguments: Any?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(marker, format, arguments) }
- }
-
- override fun warn(format: String?, arg: Any?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(format, arg) }
- }
-
- override fun warn(marker: Marker?, msg: String?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(marker, msg) }
- }
-
- override fun warn(msg: String?, t: Throwable?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(msg, t) }
- }
-
- override fun warn(format: String?, vararg arguments: Any?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(format, *arguments) }
- }
-
- override fun warn(marker: Marker?, msg: String?, t: Throwable?) {
- if (!isWarnEnabled) {
- return
- }
-
- withMdc { delegate.warn(marker, msg, t) }
- }
-
- override fun info(marker: Marker?, format: String?, vararg arguments: Any?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(marker, format, *arguments) }
- }
-
- override fun info(format: String?, arg: Any?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(format, arg) }
- }
-
- override fun info(marker: Marker?, msg: String?, t: Throwable?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(marker, msg, t) }
- }
-
- override fun info(msg: String?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(msg) }
- }
-
- override fun info(format: String?, vararg arguments: Any?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(format, *arguments) }
- }
-
- override fun info(format: String?, arg1: Any?, arg2: Any?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(format, arg1, arg2) }
- }
-
- override fun info(marker: Marker?, msg: String?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(marker, msg) }
- }
-
- override fun info(marker: Marker?, format: String?, arg: Any?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(marker, format, arg) }
- }
-
- override fun info(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(marker, format, arg1, arg2) }
- }
-
- override fun info(msg: String?, t: Throwable?) {
- if (!isInfoEnabled) {
- return
- }
-
- withMdc { delegate.info(msg, t) }
- }
-
- override fun error(msg: String?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(msg) }
- }
-
- override fun error(marker: Marker?, msg: String?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(marker, msg) }
- }
-
- override fun error(format: String?, vararg arguments: Any?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(format, *arguments) }
- }
-
- override fun error(format: String?, arg: Any?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(format, arg) }
- }
-
- override fun error(msg: String?, t: Throwable?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(msg, t) }
- }
-
- override fun error(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(marker, format, arg1, arg2) }
- }
-
- override fun error(marker: Marker?, format: String?, vararg arguments: Any?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(marker, format, *arguments) }
- }
-
- override fun error(marker: Marker?, msg: String?, t: Throwable?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(marker, msg, t) }
- }
-
- override fun error(format: String?, arg1: Any?, arg2: Any?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(format, arg1, arg2) }
- }
-
- override fun error(marker: Marker?, format: String?, arg: Any?) {
- if (!isErrorEnabled) {
- return
- }
-
- withMdc { delegate.error(marker, format, arg) }
- }
-
- override fun debug(format: String?, vararg arguments: Any?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(format, *arguments) }
- }
-
- override fun debug(format: String?, arg1: Any?, arg2: Any?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(format, arg1, arg2) }
- }
-
- override fun debug(msg: String?, t: Throwable?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(msg, t) }
- }
-
- override fun debug(format: String?, arg: Any?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(format, arg) }
- }
-
- override fun debug(marker: Marker?, msg: String?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(marker, msg) }
- }
-
- override fun debug(msg: String?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(msg) }
- }
-
- override fun debug(marker: Marker?, msg: String?, t: Throwable?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(marker, msg, t) }
- }
-
- override fun debug(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(marker, format, arg1, arg2) }
- }
-
- override fun debug(marker: Marker?, format: String?, arg: Any?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(marker, format, arg) }
- }
-
- override fun debug(marker: Marker?, format: String?, vararg arguments: Any?) {
- if (!isDebugEnabled) {
- return
- }
-
- withMdc { delegate.debug(marker, format, *arguments) }
- }
-
- override fun trace(format: String?, arg: Any?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(format, arg) }
- }
-
- override fun trace(marker: Marker?, msg: String?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(marker, msg) }
- }
-
- override fun trace(msg: String?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(msg) }
- }
-
- override fun trace(msg: String?, t: Throwable?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(msg, t) }
- }
-
- override fun trace(format: String?, arg1: Any?, arg2: Any?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(format, arg1, arg2) }
- }
-
- override fun trace(marker: Marker?, format: String?, arg1: Any?, arg2: Any?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(marker, format, arg1, arg2) }
- }
-
- override fun trace(marker: Marker?, format: String?, arg: Any?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(marker, format, arg) }
- }
-
- override fun trace(marker: Marker?, format: String?, vararg argArray: Any?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(marker, format, *argArray) }
- }
-
- override fun trace(marker: Marker?, msg: String?, t: Throwable?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(marker, msg, t) }
- }
-
- override fun trace(format: String?, vararg arguments: Any?) {
- if (!isTraceEnabled) {
- return
- }
-
- withMdc { delegate.trace(format, *arguments) }
- }
-}
diff --git a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LoggerImpl.kt b/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LoggerImpl.kt
deleted file mode 100644
index 1adcfdc0..00000000
--- a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/logging/LoggerImpl.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.odcsim.engine.omega.logging
-
-import com.atlarge.odcsim.SimulationContext
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import org.slf4j.MDC
-import org.slf4j.spi.LocationAwareLogger
-
-/**
- * An actor-specific [Logger] implementation.
- *
- * @param ctx The owning [SimulationContext] of this logger.
- */
-internal abstract class LoggerImpl internal constructor(protected val ctx: SimulationContext) : Logger {
- /**
- * Configure [MDC] with actor-specific information.
- */
- protected inline fun withMdc(block: () -> Unit) {
- MDC.put(MDC_PROCESS_REF, ctx.domain.name)
- MDC.put(MDC_PROCESS_TIME, String.format("%d", ctx.clock.millis()))
- try {
- block()
- } finally {
- MDC.remove(MDC_PROCESS_TIME)
- MDC.remove(MDC_PROCESS_REF)
- }
- }
-
- /**
- * Mapped Diagnostic Context (MDC) attribute names.
- */
- companion object {
- val MDC_PROCESS_TIME = "process.time"
- val MDC_PROCESS_REF = "process.ref"
-
- /**
- * Create a [Logger] for the specified [ActorContext].
- *
- * @param ctx The actor context to create the logger for.
- */
- operator fun invoke(ctx: SimulationContext): Logger {
- val logger = LoggerFactory.getLogger(ctx.javaClass)
- return if (logger is LocationAwareLogger) {
- LocationAwareLoggerImpl(ctx, logger)
- } else {
- LocationIgnorantLoggerImpl(ctx, logger)
- }
- }
- }
-}
diff --git a/simulator/odcsim/odcsim-engine-omega/src/main/resources/META-INF/services/com.atlarge.odcsim.SimulationEngineProvider b/simulator/odcsim/odcsim-engine-omega/src/main/resources/META-INF/services/com.atlarge.odcsim.SimulationEngineProvider
deleted file mode 100644
index 1131cebd..00000000
--- a/simulator/odcsim/odcsim-engine-omega/src/main/resources/META-INF/services/com.atlarge.odcsim.SimulationEngineProvider
+++ /dev/null
@@ -1 +0,0 @@
-com.atlarge.odcsim.engine.omega.OmegaSimulationEngineProvider
diff --git a/simulator/opendc/build.gradle.kts b/simulator/opendc-compute/build.gradle.kts
index cc3f3add..bf920306 100644
--- a/simulator/opendc/build.gradle.kts
+++ b/simulator/opendc-compute/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,3 +19,5 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
+description = "Cloud computing fabric controller of OpenDC"
diff --git a/simulator/opendc/opendc-compute/build.gradle.kts b/simulator/opendc-compute/opendc-compute-core/build.gradle.kts
index acdcd5a7..9682b50f 100644
--- a/simulator/opendc/opendc-compute/build.gradle.kts
+++ b/simulator/opendc-compute/opendc-compute-core/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2017 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-description = "Cloud computing fabric simulation model"
+description = "Core implementation of the OpenDC Compute service"
/* Build configuration */
plugins {
@@ -30,12 +28,12 @@ plugins {
}
dependencies {
- implementation(kotlin("stdlib"))
- api(project(":odcsim:odcsim-api"))
- api(project(":opendc:opendc-core"))
+ api(project(":opendc-core"))
+ implementation(project(":opendc-utils"))
implementation("io.github.microutils:kotlin-logging:1.7.9")
- testRuntimeOnly(project(":odcsim:odcsim-engine-omega"))
+ testImplementation(project(":opendc-simulator:opendc-simulator-core"))
+ testImplementation(project(":opendc-compute:opendc-compute-simulator"))
testRuntimeOnly("org.slf4j:slf4j-simple:${Library.SLF4J}")
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/Flavor.kt
index a49d3abf..e5ca115f 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/Flavor.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core
+package org.opendc.compute.core
/**
* Flavors define the compute and memory capacity of [Server] instance. To put it simply, a flavor is an available
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/Server.kt
index fd0fc836..948f622f 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/Server.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +20,14 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core
+package org.opendc.compute.core
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.core.resource.Resource
-import com.atlarge.opendc.core.resource.TagContainer
-import com.atlarge.opendc.core.services.ServiceRegistry
-import java.util.UUID
import kotlinx.coroutines.flow.Flow
+import org.opendc.compute.core.image.Image
+import org.opendc.core.resource.Resource
+import org.opendc.core.resource.TagContainer
+import org.opendc.core.services.ServiceRegistry
+import java.util.UUID
/**
* A server instance that is running on some physical or virtual machine.
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerEvent.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/ServerEvent.kt
index 1595937c..e9212832 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerEvent.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/ServerEvent.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core
-
-import com.atlarge.opendc.core.services.ServiceKey
+package org.opendc.compute.core
/**
* An event that is emitted by a [Server].
@@ -42,12 +38,4 @@ public sealed class ServerEvent {
* @property previousState The previous state of the server.
*/
public data class StateChanged(override val server: Server, val previousState: ServerState) : ServerEvent()
-
- /**
- * This event is emitted when a server publishes a service.
- *
- * @property server The server that published the service.
- * @property key The service key of the service that was published.
- */
- public data class ServicePublished(override val server: Server, val key: ServiceKey<*>) : ServerEvent()
}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/ServerState.kt
index 27372a5e..4b9d7c13 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/ServerState.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core
+package org.opendc.compute.core
/**
* An enumeration describing the possible states of a server.
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/image/EmptyImage.kt
index 8f6c4682..01f86a1b 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/image/EmptyImage.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,19 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core.image
+package org.opendc.compute.core.image
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.TagContainer
+import org.opendc.core.resource.TagContainer
import java.util.UUID
/**
* An empty boot disk [Image] that exits immediately on start.
*/
-object EmptyImage : Image {
+public object EmptyImage : Image {
override val uid: UUID = UUID.randomUUID()
override val name: String = "empty"
override val tags: TagContainer = emptyMap()
-
- override suspend fun invoke(ctx: ServerContext) {}
}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/image/Image.kt
index 52d4d7b5..e481fcc3 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/image/Image.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core.image
+package org.opendc.compute.core.image
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.Resource
+import org.opendc.core.resource.Resource
/**
* An image containing a bootable operating system that can directly be executed by physical or virtual server.
@@ -35,12 +32,4 @@ import com.atlarge.opendc.core.resource.Resource
* useful for backup purposes or for producing “gold” server images if you plan to deploy a particular server
* configuration frequently.
*/
-public interface Image : Resource {
- /**
- * Launch the machine image in the specified [ServerContext].
- *
- * This method should encapsulate and characterize the runtime behavior of the instance resulting from launching
- * the image on some machine, in terms of the resource consumption on the machine.
- */
- public suspend operator fun invoke(ctx: ServerContext)
-}
+public interface Image : Resource
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Metadata.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/Metadata.kt
index a3a851fe..11eadd87 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Metadata.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/Metadata.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal
+package org.opendc.compute.core.metal
/*
* Common metadata keys for bare-metal nodes.
@@ -31,4 +31,4 @@ package com.atlarge.opendc.compute.metal
/**
* The cluster to which the node belongs.
*/
-const val NODE_CLUSTER = "bare-metal:cluster"
+public const val NODE_CLUSTER: String = "bare-metal:cluster"
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/Node.kt
index cb637aea..6d9506f1 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/Node.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +20,13 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal
+package org.opendc.compute.core.metal
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.core.Identity
-import java.util.UUID
import kotlinx.coroutines.flow.Flow
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.image.Image
+import org.opendc.core.Identity
+import java.util.UUID
/**
* A bare-metal compute node.
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeEvent.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/NodeEvent.kt
index 7719db24..4423e2bf 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeEvent.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/NodeEvent.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal
+package org.opendc.compute.core.metal
/**
* An event that is emitted by a [Node].
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeState.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/NodeState.kt
index ca9cf509..bdc4841e 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeState.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/NodeState.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal
+package org.opendc.compute.core.metal
/**
* An enumeration describing the possible states of a bare-metal compute node.
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/driver/BareMetalDriver.kt
index 17d8ee53..9db57127 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/driver/BareMetalDriver.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,21 +20,19 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal.driver
+package org.opendc.compute.core.metal.driver
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.core.failure.FailureDomain
-import com.atlarge.opendc.core.power.Powerable
-import com.atlarge.opendc.core.services.AbstractServiceKey
-import java.util.UUID
import kotlinx.coroutines.flow.Flow
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.metal.Node
+import org.opendc.core.services.AbstractServiceKey
+import java.util.UUID
/**
* A driver interface for the management interface of a bare-metal compute node.
*/
-public interface BareMetalDriver : Powerable, FailureDomain {
+public interface BareMetalDriver {
/**
* The [Node] that is controlled by this driver.
*/
@@ -84,5 +80,5 @@ public interface BareMetalDriver : Powerable, FailureDomain {
/**
* A key that allows access to the [BareMetalDriver] instance from a [Server] that runs on the bare-metal machine.
*/
- companion object Key : AbstractServiceKey<BareMetalDriver>(UUID.randomUUID(), "bare-metal:driver")
+ public companion object Key : AbstractServiceKey<BareMetalDriver>(UUID.randomUUID(), "bare-metal:driver")
}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/service/ProvisioningService.kt
index a54d8df4..bad5b47c 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/service/ProvisioningService.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal.service
+package org.opendc.compute.core.metal.service
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
-import com.atlarge.opendc.core.services.AbstractServiceKey
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.metal.Node
+import org.opendc.compute.core.metal.driver.BareMetalDriver
+import org.opendc.core.services.AbstractServiceKey
import java.util.UUID
/**
@@ -62,5 +60,5 @@ public interface ProvisioningService {
/**
* The service key of this service.
*/
- companion object Key : AbstractServiceKey<ProvisioningService>(UUID.randomUUID(), "provisioner")
+ public companion object Key : AbstractServiceKey<ProvisioningService>(UUID.randomUUID(), "provisioner")
}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningService.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/service/SimpleProvisioningService.kt
index f6b236ae..5222f2fb 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningService.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/metal/service/SimpleProvisioningService.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,46 +20,43 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal.service
+package org.opendc.compute.core.metal.service
-import com.atlarge.odcsim.Domain
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.withContext
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.metal.Node
+import org.opendc.compute.core.metal.driver.BareMetalDriver
/**
* A very basic implementation of the [ProvisioningService].
*/
-public class SimpleProvisioningService(val domain: Domain) : ProvisioningService {
+public class SimpleProvisioningService : ProvisioningService {
/**
* The active nodes in this service.
*/
private val nodes: MutableMap<Node, BareMetalDriver> = mutableMapOf()
- override suspend fun create(driver: BareMetalDriver): Node = withContext(domain.coroutineContext) {
+ override suspend fun create(driver: BareMetalDriver): Node {
val node = driver.init()
nodes[node] = driver
- return@withContext node
+ return node
}
- override suspend fun nodes(): Set<Node> = withContext(domain.coroutineContext) { nodes.keys }
+ override suspend fun nodes(): Set<Node> = nodes.keys
- override suspend fun refresh(node: Node): Node = withContext(domain.coroutineContext) {
- return@withContext nodes[node]!!.refresh()
+ override suspend fun refresh(node: Node): Node {
+ return nodes[node]!!.refresh()
}
- override suspend fun deploy(node: Node, image: Image): Node = withContext(domain.coroutineContext) {
+ override suspend fun deploy(node: Node, image: Image): Node {
val driver = nodes[node]!!
driver.setImage(image)
- val newNode = driver.reboot()
- return@withContext newNode
+ return driver.reboot()
}
- override suspend fun stop(node: Node): Node = withContext(domain.coroutineContext) {
+ override suspend fun stop(node: Node): Node {
val driver = nodes[node]!!
- try {
+ return try {
driver.stop()
} catch (e: CancellationException) {
node
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/Hypervisor.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/Hypervisor.kt
index 1e7e351f..1ae52baa 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/Hypervisor.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/Hypervisor.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,11 +20,11 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt
+package org.opendc.compute.core.virt
-import com.atlarge.opendc.core.Identity
-import java.util.UUID
import kotlinx.coroutines.flow.Flow
+import org.opendc.core.Identity
+import java.util.UUID
/**
* A hypervisor (or virtual machine monitor) is software or firmware that virtualizes the host compute environment
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorEvent.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/HypervisorEvent.kt
index 7c088bc8..9fb437de 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorEvent.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/HypervisorEvent.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +20,10 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt
+package org.opendc.compute.core.virt
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.virt.driver.VirtDriver
/**
* An event that is emitted by a [VirtDriver].
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/InsufficientMemoryOnServerException.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/InsufficientMemoryOnServerException.kt
index 0586ae00..6fe84ea6 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/InsufficientMemoryOnServerException.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/InsufficientMemoryOnServerException.kt
@@ -1,3 +1,3 @@
-package com.atlarge.opendc.compute.virt.driver
+package org.opendc.compute.core.virt.driver
public class InsufficientMemoryOnServerException : IllegalStateException("Insufficient memory left on server.")
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/VirtDriver.kt
index b1844f67..5ecfd357 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/VirtDriver.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,15 +20,14 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt.driver
+package org.opendc.compute.core.virt.driver
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.virt.HypervisorEvent
-import com.atlarge.opendc.core.services.AbstractServiceKey
-import java.util.UUID
import kotlinx.coroutines.flow.Flow
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.virt.HypervisorEvent
+import org.opendc.core.services.AbstractServiceKey
+import java.util.UUID
/**
* A driver interface for a hypervisor running on some host server and communicating with the central compute service to
@@ -50,7 +47,11 @@ public interface VirtDriver {
* @param flavor The flavor of the server which this driver is controlling.
* @return The virtual server spawned by this method.
*/
- public suspend fun spawn(name: String, image: Image, flavor: Flavor): Server
+ public suspend fun spawn(
+ name: String,
+ image: Image,
+ flavor: org.opendc.compute.core.Flavor
+ ): Server
- companion object Key : AbstractServiceKey<VirtDriver>(UUID.randomUUID(), "virtual-driver")
+ public companion object Key : AbstractServiceKey<VirtDriver>(UUID.randomUUID(), "virtual-driver")
}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningEvent.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/service/VirtProvisioningEvent.kt
index c3fb99f9..abd2fc95 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningEvent.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/service/VirtProvisioningEvent.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt.service
+package org.opendc.compute.core.virt.service
/**
* An event that is emitted by the [VirtProvisioningService].
@@ -36,7 +36,7 @@ public sealed class VirtProvisioningEvent {
/**
* An event emitted for writing metrics.
*/
- data class MetricsAvailable(
+ public data class MetricsAvailable(
override val provisioner: VirtProvisioningService,
public val totalHostCount: Int,
public val availableHostCount: Int,
diff --git a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationEngine.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/service/VirtProvisioningService.kt
index db05cb1d..ab96e0a3 100644
--- a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationEngine.kt
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/service/VirtProvisioningService.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2018 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,37 +20,42 @@
* SOFTWARE.
*/
-package com.atlarge.odcsim
+package org.opendc.compute.core.virt.service
+
+import kotlinx.coroutines.flow.Flow
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.virt.driver.VirtDriver
/**
- * An engine for managing logical processes represented as [Behavior] during simulation.
- *
- * An implementation of this interface should be provided by an engine. See for example *odcsim-engine-omega*,
- * which is the reference implementation of the *odcsim* API.
+ * A service for VM provisioning on a cloud.
*/
-public interface SimulationEngine {
- /**
- * The name of this engine instance, used to distinguish between multiple engines running within the same JVM.
- */
- public val name: String
-
+public interface VirtProvisioningService {
/**
- * Construct an anonymous root simulation domain.
+ * The events emitted by the service.
*/
- public fun newDomain(): Domain
+ public val events: Flow<VirtProvisioningEvent>
/**
- * Construct a new root simulation domain with the specified [name].
+ * Obtain the active hypervisors for this provisioner.
*/
- public fun newDomain(name: String): Domain
+ public suspend fun drivers(): Set<VirtDriver>
/**
- * Run the simulation.
+ * Submit the specified [Image] to the provisioning service.
+ *
+ * @param name The name of the server to deploy.
+ * @param image The image to be deployed.
+ * @param flavor The flavor of the machine instance to run this [image] on.
*/
- public suspend fun run()
+ public suspend fun deploy(
+ name: String,
+ image: Image,
+ flavor: org.opendc.compute.core.Flavor
+ ): Server
/**
- * Terminates this engine in an asynchronous fashion.
+ * Terminate the provisioning service releasing all the leased bare-metal machines.
*/
public suspend fun terminate()
}
diff --git a/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/workload/VmWorkload.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/workload/VmWorkload.kt
new file mode 100644
index 00000000..6c724277
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/workload/VmWorkload.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.core.workload
+
+import org.opendc.compute.core.image.Image
+import org.opendc.core.User
+import org.opendc.core.workload.Workload
+import java.util.UUID
+
+/**
+ * A workload that represents a VM.
+ *
+ * @property uid A unique identified of this VM.
+ * @property name The name of this VM.
+ * @property owner The owner of the VM.
+ * @property image The image of the VM.
+ */
+public data class VmWorkload(
+ override val uid: UUID,
+ override val name: String,
+ override val owner: User,
+ val image: Image
+) : Workload {
+ override fun equals(other: Any?): Boolean = other is VmWorkload && uid == other.uid
+
+ override fun hashCode(): Int = uid.hashCode()
+}
diff --git a/simulator/odcsim/odcsim-engine-omega/build.gradle.kts b/simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts
index 98e2469e..d7570e54 100644
--- a/simulator/odcsim/odcsim-engine-omega/build.gradle.kts
+++ b/simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2018 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,26 +20,23 @@
* SOFTWARE.
*/
-description = "Single-threaded reference implementation for the odcsim API"
+description = "Simulator for OpenDC Compute"
/* Build configuration */
plugins {
`kotlin-library-convention`
}
-/* Project configuration */
-repositories {
- jcenter()
-}
-
dependencies {
- api(project(":odcsim:odcsim-api"))
-
- implementation(kotlin("stdlib"))
- implementation("org.jetbrains:annotations:17.0.0")
+ api(project(":opendc-compute:opendc-compute-core"))
+ implementation(project(":opendc-utils"))
+ implementation("io.github.microutils:kotlin-logging:1.7.9")
+ implementation(project(":opendc-simulator:opendc-simulator-compute"))
+ api(project(":opendc-simulator:opendc-simulator-failures"))
+ testImplementation(project(":opendc-simulator:opendc-simulator-core"))
+ testRuntimeOnly("org.slf4j:slf4j-simple:${Library.SLF4J}")
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
testImplementation("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}")
- testRuntimeOnly("org.slf4j:slf4j-simple:${Library.SLF4J}")
}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/ComputeSimExecutionContext.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/ComputeSimExecutionContext.kt
new file mode 100644
index 00000000..153a86b3
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/ComputeSimExecutionContext.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator
+
+import org.opendc.compute.core.Server
+import org.opendc.simulator.compute.SimExecutionContext
+
+/**
+ * Extended [SimExecutionContext] in which workloads within the OpenDC Compute module run.
+ */
+public interface ComputeSimExecutionContext : SimExecutionContext {
+ /**
+ * The server on which the image runs.
+ */
+ public val server: Server
+}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/HypervisorView.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/HypervisorView.kt
new file mode 100644
index 00000000..1a79523e
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/HypervisorView.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator
+
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.virt.driver.VirtDriver
+import java.util.UUID
+
+public class HypervisorView(
+ public val uid: UUID,
+ public var server: Server,
+ public var numberOfActiveServers: Int,
+ public var availableMemory: Long,
+ public var provisionedCores: Int
+) {
+ public lateinit var driver: VirtDriver
+}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt
new file mode 100644
index 00000000..97f550ba
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.Flow
+import org.opendc.compute.core.Flavor
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.ServerEvent
+import org.opendc.compute.core.ServerState
+import org.opendc.compute.core.image.EmptyImage
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.metal.Node
+import org.opendc.compute.core.metal.NodeEvent
+import org.opendc.compute.core.metal.NodeState
+import org.opendc.compute.core.metal.driver.BareMetalDriver
+import org.opendc.compute.simulator.power.ConstantPowerModel
+import org.opendc.compute.simulator.power.PowerModel
+import org.opendc.compute.simulator.power.Powerable
+import org.opendc.core.services.ServiceRegistry
+import org.opendc.simulator.compute.SimBareMetalMachine
+import org.opendc.simulator.compute.SimExecutionContext
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.workload.SimWorkload
+import org.opendc.simulator.failures.FailureDomain
+import org.opendc.utils.flow.EventFlow
+import org.opendc.utils.flow.StateFlow
+import java.time.Clock
+import java.util.UUID
+import kotlin.random.Random
+
+/**
+ * A basic implementation of the [BareMetalDriver] that simulates an [Image] running on a bare-metal machine.
+ *
+ * @param coroutineScope The [CoroutineScope] the driver runs in.
+ * @param clock The virtual clock to keep track of time.
+ * @param uid The unique identifier of the machine.
+ * @param name An optional name of the machine.
+ * @param metadata The initial metadata of the node.
+ * @param machine The machine model to simulate.
+ * @param powerModel The power model of this machine.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+public class SimBareMetalDriver(
+ private val coroutineScope: CoroutineScope,
+ private val clock: Clock,
+ uid: UUID,
+ name: String,
+ metadata: Map<String, Any>,
+ machine: SimMachineModel,
+ powerModel: PowerModel<SimBareMetalDriver> = ConstantPowerModel(0.0)
+) : BareMetalDriver, FailureDomain, Powerable {
+ /**
+ * The flavor that corresponds to this machine.
+ */
+ private val flavor = Flavor(
+ machine.cpus.size,
+ machine.memory.map { it.size }.sum()
+ )
+
+ /**
+ * The events of the machine.
+ */
+ private val events = EventFlow<NodeEvent>()
+
+ /**
+ * The machine state.
+ */
+ private val nodeState =
+ StateFlow(Node(uid, name, metadata + ("driver" to this), NodeState.SHUTOFF, EmptyImage, null, events))
+
+ /**
+ * The [SimBareMetalMachine] we use to run the workload.
+ */
+ private val machine = SimBareMetalMachine(coroutineScope, clock, machine)
+
+ override val node: Flow<Node> = nodeState
+
+ override val usage: Flow<Double>
+ get() = this.machine.usage
+
+ override val powerDraw: Flow<Double> = powerModel(this)
+
+ /**
+ * The internal random instance.
+ */
+ private val random = Random(uid.leastSignificantBits xor uid.mostSignificantBits)
+
+ /**
+ * The [Job] that runs the simulated workload.
+ */
+ private var job: Job? = null
+
+ /**
+ * The event stream to publish to for the server.
+ */
+ private var serverEvents: EventFlow<ServerEvent>? = null
+
+ override suspend fun init(): Node {
+ return nodeState.value
+ }
+
+ override suspend fun start(): Node {
+ val node = nodeState.value
+ if (node.state != NodeState.SHUTOFF) {
+ return node
+ }
+
+ val events = EventFlow<ServerEvent>()
+ serverEvents = events
+ val server = Server(
+ UUID(random.nextLong(), random.nextLong()),
+ node.name,
+ emptyMap(),
+ flavor,
+ node.image,
+ ServerState.BUILD,
+ ServiceRegistry().put(BareMetalDriver, this@SimBareMetalDriver),
+ events
+ )
+
+ // Wrap the workload to pass in a ComputeSimExecutionContext
+ val workload = object : SimWorkload {
+ override suspend fun run(ctx: SimExecutionContext) {
+ val wrappedCtx = object : ComputeSimExecutionContext, SimExecutionContext by ctx {
+ override val server: Server
+ get() = nodeState.value.server!!
+ }
+ (node.image as SimWorkloadImage).workload.run(wrappedCtx)
+ }
+ }
+
+ job = coroutineScope.launch {
+ delay(1) // TODO Introduce boot time
+ initMachine()
+ try {
+ machine.run(workload)
+ exitMachine(null)
+ } catch (_: CancellationException) {
+ // Ignored
+ } catch (cause: Throwable) {
+ exitMachine(cause)
+ }
+ }
+
+ setNode(node.copy(state = NodeState.BOOT, server = server))
+ return nodeState.value
+ }
+
+ private fun initMachine() {
+ val server = nodeState.value.server?.copy(state = ServerState.ACTIVE)
+ setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
+ }
+
+ private fun exitMachine(cause: Throwable?) {
+ val newServerState =
+ if (cause == null)
+ ServerState.SHUTOFF
+ else
+ ServerState.ERROR
+ val newNodeState =
+ if (cause == null)
+ nodeState.value.state
+ else
+ NodeState.ERROR
+ val server = nodeState.value.server?.copy(state = newServerState)
+ setNode(nodeState.value.copy(state = newNodeState, server = server))
+
+ serverEvents?.close()
+ serverEvents = null
+ }
+
+ override suspend fun stop(): Node {
+ val node = nodeState.value
+ if (node.state == NodeState.SHUTOFF) {
+ return node
+ }
+
+ job?.cancelAndJoin()
+ setNode(node.copy(state = NodeState.SHUTOFF, server = null))
+ return node
+ }
+
+ override suspend fun reboot(): Node {
+ stop()
+ return start()
+ }
+
+ override suspend fun setImage(image: Image): Node {
+ setNode(nodeState.value.copy(image = image))
+ return nodeState.value
+ }
+
+ override suspend fun refresh(): Node = nodeState.value
+
+ private fun setNode(value: Node) {
+ val field = nodeState.value
+ if (field.state != value.state) {
+ events.emit(NodeEvent.StateChanged(value, field.state))
+ }
+
+ val oldServer = field.server
+ val newServer = value.server
+
+ if (oldServer != null && newServer != null && oldServer.state != newServer.state) {
+ serverEvents?.emit(ServerEvent.StateChanged(newServer, oldServer.state))
+ }
+
+ nodeState.value = value
+ }
+
+ override val scope: CoroutineScope
+ get() = coroutineScope
+
+ override suspend fun fail() {
+ val server = nodeState.value.server?.copy(state = ServerState.ERROR)
+ setNode(nodeState.value.copy(state = NodeState.ERROR, server = server))
+ }
+
+ override suspend fun recover() {
+ val server = nodeState.value.server?.copy(state = ServerState.ACTIVE)
+ setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
+ }
+
+ override fun toString(): String = "SimBareMetalDriver(node = ${nodeState.value.uid})"
+}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt
new file mode 100644
index 00000000..09eec1ef
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator
+
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.launch
+import org.opendc.compute.core.*
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.virt.HypervisorEvent
+import org.opendc.compute.core.virt.driver.InsufficientMemoryOnServerException
+import org.opendc.compute.core.virt.driver.VirtDriver
+import org.opendc.core.services.ServiceRegistry
+import org.opendc.simulator.compute.SimExecutionContext
+import org.opendc.simulator.compute.SimHypervisor
+import org.opendc.simulator.compute.SimMachine
+import org.opendc.simulator.compute.interference.IMAGE_PERF_INTERFERENCE_MODEL
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
+import org.opendc.simulator.compute.workload.SimWorkload
+import org.opendc.utils.flow.EventFlow
+import java.time.Clock
+import java.util.*
+
+/**
+ * A [VirtDriver] that is simulates virtual machines on a physical machine using [SimHypervisor].
+ */
+public class SimVirtDriver(
+ private val coroutineScope: CoroutineScope,
+ clock: Clock,
+ private val ctx: SimExecutionContext
+) : VirtDriver {
+
+ /**
+ * The server hosting this hypervisor.
+ */
+ public val server: Server
+ get() = (ctx as ComputeSimExecutionContext).server
+
+ /**
+ * The [EventFlow] to emit the events.
+ */
+ internal val eventFlow = EventFlow<HypervisorEvent>()
+
+ override val events: Flow<HypervisorEvent> = eventFlow
+
+ /**
+ * Current total memory use of the images on this hypervisor.
+ */
+ private var availableMemory: Long = ctx.machine.memory.map { it.size }.sum()
+
+ /**
+ * The hypervisor to run multiple workloads.
+ */
+ private val hypervisor = SimHypervisor(
+ coroutineScope,
+ clock,
+ object : SimHypervisor.Listener {
+ override fun onSliceFinish(
+ hypervisor: SimHypervisor,
+ requestedBurst: Long,
+ grantedBurst: Long,
+ overcommissionedBurst: Long,
+ interferedBurst: Long,
+ cpuUsage: Double,
+ cpuDemand: Double
+ ) {
+ eventFlow.emit(
+ HypervisorEvent.SliceFinished(
+ this@SimVirtDriver,
+ requestedBurst,
+ grantedBurst,
+ overcommissionedBurst,
+ interferedBurst,
+ cpuUsage,
+ cpuDemand,
+ vms.size,
+ (ctx as ComputeSimExecutionContext).server
+ )
+ )
+ }
+ }
+ )
+
+ /**
+ * The virtual machines running on the hypervisor.
+ */
+ private val vms = HashSet<VirtualMachine>()
+
+ override suspend fun spawn(name: String, image: Image, flavor: Flavor): Server {
+ val requiredMemory = flavor.memorySize
+ if (availableMemory - requiredMemory < 0) {
+ throw InsufficientMemoryOnServerException()
+ }
+ require(flavor.cpuCount <= ctx.machine.cpus.size) { "Machine does not fit" }
+
+ val events = EventFlow<ServerEvent>()
+ val server = Server(
+ UUID.randomUUID(),
+ name,
+ emptyMap(),
+ flavor,
+ image,
+ ServerState.BUILD,
+ ServiceRegistry(),
+ events
+ )
+ availableMemory -= requiredMemory
+ val vm = VirtualMachine(server, events, hypervisor.createMachine(ctx.machine))
+ vms.add(vm)
+ vmStarted(vm)
+ eventFlow.emit(HypervisorEvent.VmsUpdated(this, vms.size, availableMemory))
+ return server
+ }
+
+ private fun vmStarted(vm: VirtualMachine) {
+ vms.forEach { it ->
+ vm.performanceInterferenceModel?.onStart(it.server.image.name)
+ }
+ }
+
+ private fun vmStopped(vm: VirtualMachine) {
+ vms.forEach { it ->
+ vm.performanceInterferenceModel?.onStop(it.server.image.name)
+ }
+ }
+
+ /**
+ * A virtual machine instance that the driver manages.
+ */
+ private inner class VirtualMachine(server: Server, val events: EventFlow<ServerEvent>, machine: SimMachine) {
+ val performanceInterferenceModel: PerformanceInterferenceModel? = server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel?
+
+ val job = coroutineScope.launch {
+ val workload = object : SimWorkload {
+ override suspend fun run(ctx: SimExecutionContext) {
+ val wrappedCtx = object : ComputeSimExecutionContext, SimExecutionContext by ctx {
+ override val server: Server
+ get() = this@VirtualMachine.server
+ }
+ (server.image as SimWorkloadImage).workload.run(wrappedCtx)
+ }
+ }
+
+ delay(1) // TODO Introduce boot time
+ init()
+ try {
+ machine.run(workload)
+ exit(null)
+ } catch (cause: Throwable) {
+ exit(cause)
+ }
+ }
+
+ var server: Server = server
+ set(value) {
+ if (field.state != value.state) {
+ events.emit(ServerEvent.StateChanged(value, field.state))
+ }
+
+ field = value
+ }
+
+ private fun init() {
+ server = server.copy(state = ServerState.ACTIVE)
+ }
+
+ private fun exit(cause: Throwable?) {
+ val serverState =
+ if (cause == null)
+ ServerState.SHUTOFF
+ else
+ ServerState.ERROR
+ server = server.copy(state = serverState)
+ availableMemory += server.flavor.memorySize
+ vms.remove(this)
+ vmStopped(this)
+ eventFlow.emit(HypervisorEvent.VmsUpdated(this@SimVirtDriver, vms.size, availableMemory))
+ events.close()
+ }
+ }
+
+ public suspend fun run() {
+ hypervisor.run(ctx)
+ }
+}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriverWorkload.kt
index 5a9b725b..58b9408a 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriverWorkload.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,19 +20,19 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core.execution
+package org.opendc.compute.simulator
-/**
- * An extended [ServerContext] providing several methods for managing the execution context.
- */
-public interface ServerManagementContext : ServerContext {
- /**
- * Initialize the management context.
- */
- public suspend fun init()
+import kotlinx.coroutines.coroutineScope
+import org.opendc.simulator.compute.SimExecutionContext
+import org.opendc.simulator.compute.workload.SimWorkload
+
+public class SimVirtDriverWorkload : SimWorkload {
+ public lateinit var driver: SimVirtDriver
- /**
- * Terminate the execution of the server.
- */
- public suspend fun exit(cause: Throwable? = null)
+ override suspend fun run(ctx: SimExecutionContext) {
+ coroutineScope {
+ driver = SimVirtDriver(this, ctx.clock, ctx)
+ driver.run()
+ }
+ }
}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt
new file mode 100644
index 00000000..e83370d7
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import mu.KotlinLogging
+import org.opendc.compute.core.Flavor
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.ServerEvent
+import org.opendc.compute.core.ServerState
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.compute.core.virt.HypervisorEvent
+import org.opendc.compute.core.virt.driver.InsufficientMemoryOnServerException
+import org.opendc.compute.core.virt.driver.VirtDriver
+import org.opendc.compute.core.virt.service.VirtProvisioningEvent
+import org.opendc.compute.core.virt.service.VirtProvisioningService
+import org.opendc.compute.simulator.allocation.AllocationPolicy
+import org.opendc.utils.flow.EventFlow
+import java.time.Clock
+import java.util.*
+import kotlin.coroutines.Continuation
+import kotlin.coroutines.resume
+import kotlin.math.max
+
+@OptIn(ExperimentalCoroutinesApi::class)
+public class SimVirtProvisioningService(
+ private val coroutineScope: CoroutineScope,
+ private val clock: Clock,
+ private val provisioningService: ProvisioningService,
+ public val allocationPolicy: AllocationPolicy
+) : VirtProvisioningService {
+ /**
+ * The logger instance to use.
+ */
+ private val logger = KotlinLogging.logger {}
+
+ /**
+ * The hypervisors that have been launched by the service.
+ */
+ private val hypervisors: MutableMap<Server, HypervisorView> = mutableMapOf()
+
+ /**
+ * The available hypervisors.
+ */
+ private val availableHypervisors: MutableSet<HypervisorView> = mutableSetOf()
+
+ /**
+ * The incoming images to be processed by the provisioner.
+ */
+ private val incomingImages: MutableSet<ImageView> = mutableSetOf()
+
+ /**
+ * The active images in the system.
+ */
+ private val activeImages: MutableSet<ImageView> = mutableSetOf()
+
+ public var submittedVms: Int = 0
+ public var queuedVms: Int = 0
+ public var runningVms: Int = 0
+ public var finishedVms: Int = 0
+ public var unscheduledVms: Int = 0
+
+ private var maxCores = 0
+ private var maxMemory = 0L
+
+ /**
+ * The allocation logic to use.
+ */
+ private val allocationLogic = allocationPolicy()
+
+ /**
+ * The [EventFlow] to emit the events.
+ */
+ internal val eventFlow = EventFlow<VirtProvisioningEvent>()
+
+ override val events: Flow<VirtProvisioningEvent> = eventFlow
+
+ init {
+ coroutineScope.launch {
+ val provisionedNodes = provisioningService.nodes()
+ provisionedNodes.forEach { node ->
+ val workload = SimVirtDriverWorkload()
+ val hypervisorImage = SimWorkloadImage(UUID.randomUUID(), "vmm", emptyMap(), workload)
+ launch {
+ var init = false
+ val deployedNode = provisioningService.deploy(node, hypervisorImage)
+ val server = deployedNode.server!!
+ server.events.onEach { event ->
+ when (event) {
+ is ServerEvent.StateChanged -> {
+ if (!init) {
+ init = true
+ }
+ stateChanged(event.server)
+ }
+ }
+ }.launchIn(this)
+
+ delay(1)
+ onHypervisorAvailable(server, workload.driver)
+ }
+ }
+ }
+ }
+
+ override suspend fun drivers(): Set<VirtDriver> {
+ return availableHypervisors.map { it.driver }.toSet()
+ }
+
+ override suspend fun deploy(
+ name: String,
+ image: Image,
+ flavor: Flavor
+ ): Server {
+ eventFlow.emit(
+ VirtProvisioningEvent.MetricsAvailable(
+ this@SimVirtProvisioningService,
+ hypervisors.size,
+ availableHypervisors.size,
+ ++submittedVms,
+ runningVms,
+ finishedVms,
+ ++queuedVms,
+ unscheduledVms
+ )
+ )
+
+ return suspendCancellableCoroutine<Server> { cont ->
+ val vmInstance = ImageView(name, image, flavor, cont)
+ incomingImages += vmInstance
+ requestCycle()
+ }
+ }
+
+ override suspend fun terminate() {
+ val provisionedNodes = provisioningService.nodes()
+ provisionedNodes.forEach { node -> provisioningService.stop(node) }
+ }
+
+ private var call: Job? = null
+
+ private fun requestCycle() {
+ if (call != null) {
+ return
+ }
+
+ val quantum = 300000 // 5 minutes in milliseconds
+ // We assume that the provisioner runs at a fixed slot every time quantum (e.g t=0, t=60, t=120).
+ // This is important because the slices of the VMs need to be aligned.
+ // We calculate here the delay until the next scheduling slot.
+ val delay = quantum - (clock.millis() % quantum)
+
+ val call = coroutineScope.launch {
+ delay(delay)
+ this@SimVirtProvisioningService.call = null
+ schedule()
+ }
+ this.call = call
+ }
+
+ private suspend fun schedule() {
+ val imagesToBeScheduled = incomingImages.toSet()
+
+ for (imageInstance in imagesToBeScheduled) {
+ val requiredMemory = imageInstance.image.tags["required-memory"] as Long
+ val selectedHv = allocationLogic.select(availableHypervisors, imageInstance)
+
+ if (selectedHv == null) {
+ if (requiredMemory > maxMemory || imageInstance.flavor.cpuCount > maxCores) {
+ eventFlow.emit(
+ VirtProvisioningEvent.MetricsAvailable(
+ this@SimVirtProvisioningService,
+ hypervisors.size,
+ availableHypervisors.size,
+ submittedVms,
+ runningVms,
+ finishedVms,
+ queuedVms,
+ ++unscheduledVms
+ )
+ )
+
+ incomingImages -= imageInstance
+
+ logger.warn("Failed to spawn ${imageInstance.image}: does not fit [${clock.millis()}]")
+ continue
+ } else {
+ break
+ }
+ }
+
+ try {
+ logger.info { "[${clock.millis()}] Spawning ${imageInstance.image} on ${selectedHv.server.uid} ${selectedHv.server.name} ${selectedHv.server.flavor}" }
+ incomingImages -= imageInstance
+
+ // Speculatively update the hypervisor view information to prevent other images in the queue from
+ // deciding on stale values.
+ selectedHv.numberOfActiveServers++
+ selectedHv.provisionedCores += imageInstance.flavor.cpuCount
+ selectedHv.availableMemory -= requiredMemory // XXX Temporary hack
+
+ val server = selectedHv.driver.spawn(
+ imageInstance.name,
+ imageInstance.image,
+ imageInstance.flavor
+ )
+ imageInstance.server = server
+ imageInstance.continuation.resume(server)
+
+ eventFlow.emit(
+ VirtProvisioningEvent.MetricsAvailable(
+ this@SimVirtProvisioningService,
+ hypervisors.size,
+ availableHypervisors.size,
+ submittedVms,
+ ++runningVms,
+ finishedVms,
+ --queuedVms,
+ unscheduledVms
+ )
+ )
+ activeImages += imageInstance
+
+ server.events
+ .onEach { event ->
+ when (event) {
+ is ServerEvent.StateChanged -> {
+ if (event.server.state == ServerState.SHUTOFF) {
+ logger.info { "[${clock.millis()}] Server ${event.server.uid} ${event.server.name} ${event.server.flavor} finished." }
+
+ eventFlow.emit(
+ VirtProvisioningEvent.MetricsAvailable(
+ this@SimVirtProvisioningService,
+ hypervisors.size,
+ availableHypervisors.size,
+ submittedVms,
+ --runningVms,
+ ++finishedVms,
+ queuedVms,
+ unscheduledVms
+ )
+ )
+
+ activeImages -= imageInstance
+ selectedHv.provisionedCores -= server.flavor.cpuCount
+
+ // Try to reschedule if needed
+ if (incomingImages.isNotEmpty()) {
+ requestCycle()
+ }
+ }
+ }
+ }
+ }
+ .launchIn(coroutineScope)
+ } catch (e: InsufficientMemoryOnServerException) {
+ logger.error("Failed to deploy VM", e)
+
+ selectedHv.numberOfActiveServers--
+ selectedHv.provisionedCores -= imageInstance.flavor.cpuCount
+ selectedHv.availableMemory += requiredMemory
+ } catch (e: Throwable) {
+ logger.error("Failed to deploy VM", e)
+ }
+ }
+ }
+
+ private fun stateChanged(server: Server) {
+ when (server.state) {
+ ServerState.ACTIVE -> {
+ logger.debug { "[${clock.millis()}] Server ${server.uid} available: ${server.state}" }
+
+ if (server in hypervisors) {
+ // Corner case for when the hypervisor already exists
+ availableHypervisors += hypervisors.getValue(server)
+ } else {
+ val hv = HypervisorView(
+ server.uid,
+ server,
+ 0,
+ server.flavor.memorySize,
+ 0
+ )
+ maxCores = max(maxCores, server.flavor.cpuCount)
+ maxMemory = max(maxMemory, server.flavor.memorySize)
+ hypervisors[server] = hv
+ }
+
+ eventFlow.emit(
+ VirtProvisioningEvent.MetricsAvailable(
+ this@SimVirtProvisioningService,
+ hypervisors.size,
+ availableHypervisors.size,
+ submittedVms,
+ runningVms,
+ finishedVms,
+ queuedVms,
+ unscheduledVms
+ )
+ )
+
+ // Re-schedule on the new machine
+ if (incomingImages.isNotEmpty()) {
+ requestCycle()
+ }
+ }
+ ServerState.SHUTOFF, ServerState.ERROR -> {
+ logger.debug { "[${clock.millis()}] Server ${server.uid} unavailable: ${server.state}" }
+ val hv = hypervisors[server] ?: return
+ availableHypervisors -= hv
+
+ eventFlow.emit(
+ VirtProvisioningEvent.MetricsAvailable(
+ this@SimVirtProvisioningService,
+ hypervisors.size,
+ availableHypervisors.size,
+ submittedVms,
+ runningVms,
+ finishedVms,
+ queuedVms,
+ unscheduledVms
+ )
+ )
+
+ if (incomingImages.isNotEmpty()) {
+ requestCycle()
+ }
+ }
+ else -> throw IllegalStateException()
+ }
+ }
+
+ private fun onHypervisorAvailable(server: Server, hypervisor: SimVirtDriver) {
+ val hv = hypervisors[server] ?: return
+ hv.driver = hypervisor
+ availableHypervisors += hv
+
+ eventFlow.emit(
+ VirtProvisioningEvent.MetricsAvailable(
+ this@SimVirtProvisioningService,
+ hypervisors.size,
+ availableHypervisors.size,
+ submittedVms,
+ runningVms,
+ finishedVms,
+ queuedVms,
+ unscheduledVms
+ )
+ )
+
+ hv.driver.events
+ .onEach { event ->
+ if (event is HypervisorEvent.VmsUpdated) {
+ hv.numberOfActiveServers = event.numberOfActiveServers
+ hv.availableMemory = event.availableMemory
+ }
+ }.launchIn(coroutineScope)
+
+ requestCycle()
+ }
+
+ public data class ImageView(
+ public val name: String,
+ public val image: Image,
+ public val flavor: Flavor,
+ public val continuation: Continuation<Server>,
+ public var server: Server? = null
+ )
+}
diff --git a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngineProvider.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimWorkloadImage.kt
index 5dba3233..b48de1d5 100644
--- a/simulator/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngineProvider.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimWorkloadImage.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2018 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,24 @@
* SOFTWARE.
*/
-package com.atlarge.odcsim.engine.omega
+package org.opendc.compute.simulator
-import com.atlarge.odcsim.SimulationEngine
-import com.atlarge.odcsim.SimulationEngineProvider
-import java.util.ServiceLoader
+import org.opendc.compute.core.image.Image
+import org.opendc.core.resource.TagContainer
+import org.opendc.simulator.compute.workload.SimWorkload
+import java.util.*
/**
- * An [SimulationEngineProvider] for the Omega engine, used by the [ServiceLoader] API to create
- * [OmegaSimulationEngine] instances.
+ * An application [Image] that runs a [SimWorkload].
+ *
+ * @property uid The unique identifier of this image.
+ * @property name The name of this image.
+ * @property tags The tags attached to the image.
+ * @property workload The workload to run for this image.
*/
-public class OmegaSimulationEngineProvider : SimulationEngineProvider {
- override operator fun invoke(name: String): SimulationEngine = OmegaSimulationEngine(name)
-}
+public data class SimWorkloadImage(
+ public override val uid: UUID,
+ public override val name: String,
+ public override val tags: TagContainer,
+ public val workload: SimWorkload
+) : Image
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AllocationPolicy.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AllocationPolicy.kt
new file mode 100644
index 00000000..2018b9f2
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AllocationPolicy.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.allocation
+
+import org.opendc.compute.core.metal.Node
+import org.opendc.compute.simulator.HypervisorView
+import org.opendc.compute.simulator.SimVirtProvisioningService
+
+/**
+ * A policy for selecting the [Node] an image should be deployed to,
+ */
+public interface AllocationPolicy {
+ /**
+ * The logic of the allocation policy.
+ */
+ public interface Logic {
+ /**
+ * Select the node on which the server should be scheduled.
+ */
+ public fun select(
+ hypervisors: Set<HypervisorView>,
+ image: SimVirtProvisioningService.ImageView
+ ): HypervisorView?
+ }
+
+ /**
+ * Builds the logic of the policy.
+ */
+ public operator fun invoke(): Logic
+}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableCoreMemoryAllocationPolicy.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AvailableCoreMemoryAllocationPolicy.kt
index 79b622d2..38a07b2b 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableCoreMemoryAllocationPolicy.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AvailableCoreMemoryAllocationPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt.service.allocation
+package org.opendc.compute.simulator.allocation
-import com.atlarge.opendc.compute.virt.service.HypervisorView
+import org.opendc.compute.simulator.HypervisorView
/**
* An [AllocationPolicy] that selects the machine with the highest/lowest amount of memory per core.
*
* @param reversed An option to reverse the order of the machines (lower amount of memory scores better).
*/
-public class AvailableCoreMemoryAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
+public class AvailableCoreMemoryAllocationPolicy(private val reversed: Boolean = false) : AllocationPolicy {
override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
override val comparator: Comparator<HypervisorView> =
compareBy<HypervisorView> { -it.availableMemory / it.server.flavor.cpuCount }
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AvailableMemoryAllocationPolicy.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AvailableMemoryAllocationPolicy.kt
new file mode 100644
index 00000000..e87abd7b
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/AvailableMemoryAllocationPolicy.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.allocation
+
+import org.opendc.compute.simulator.HypervisorView
+
+/**
+ * Allocation policy that selects the node with the most available memory.
+ *
+ * @param reversed A flag to reverse the order (least amount of memory scores the best).
+ */
+public class AvailableMemoryAllocationPolicy(public val reversed: Boolean = false) : AllocationPolicy {
+ override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
+ override val comparator: Comparator<HypervisorView> = compareBy<HypervisorView> { -it.availableMemory }
+ .run { if (reversed) reversed() else this }
+ }
+}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ComparableAllocationPolicyLogic.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ComparableAllocationPolicyLogic.kt
index 79dd95f3..8defe8b7 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ComparableAllocationPolicyLogic.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ComparableAllocationPolicyLogic.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,15 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt.service.allocation
+package org.opendc.compute.simulator.allocation
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
+import org.opendc.compute.simulator.HypervisorView
+import org.opendc.compute.simulator.SimVirtProvisioningService
/**
* The logic for an [AllocationPolicy] that uses a [Comparator] to select the appropriate node.
*/
-interface ComparableAllocationPolicyLogic : AllocationPolicy.Logic {
+public interface ComparableAllocationPolicyLogic : AllocationPolicy.Logic {
/**
* The comparator to use.
*/
@@ -39,14 +36,14 @@ interface ComparableAllocationPolicyLogic : AllocationPolicy.Logic {
override fun select(
hypervisors: Set<HypervisorView>,
- image: SimpleVirtProvisioningService.ImageView
+ image: SimVirtProvisioningService.ImageView
): HypervisorView? {
return hypervisors.asSequence()
.filter { hv ->
- val fitsMemory = hv.availableMemory >= (image.image as VmImage).requiredMemory
+ val fitsMemory = hv.availableMemory >= (image.image.tags["required-memory"] as Long)
val fitsCpu = hv.server.flavor.cpuCount >= image.flavor.cpuCount
fitsMemory && fitsCpu
}
- .minWith(comparator.thenBy { it.server.uid })
+ .minWithOrNull(comparator.thenBy { it.server.uid })
}
}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/NumberOfActiveServersAllocationPolicy.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/NumberOfActiveServersAllocationPolicy.kt
new file mode 100644
index 00000000..5e2b895c
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/NumberOfActiveServersAllocationPolicy.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.allocation
+
+import org.opendc.compute.simulator.HypervisorView
+
+/**
+ * Allocation policy that selects the node with the least amount of active servers.
+ *
+ * @param reversed A flag to reverse the order, such that the node with the most active servers is selected.
+ */
+public class NumberOfActiveServersAllocationPolicy(public val reversed: Boolean = false) : AllocationPolicy {
+ override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
+ override val comparator: Comparator<HypervisorView> = compareBy<HypervisorView> { it.numberOfActiveServers }
+ .run { if (reversed) reversed() else this }
+ }
+}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ProvisionedCoresAllocationPolicy.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ProvisionedCoresAllocationPolicy.kt
index e1a995a0..4344d979 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ProvisionedCoresAllocationPolicy.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ProvisionedCoresAllocationPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt.service.allocation
+package org.opendc.compute.simulator.allocation
-import com.atlarge.opendc.compute.virt.service.HypervisorView
+import org.opendc.compute.simulator.HypervisorView
/**
* An [AllocationPolicy] that takes into account the number of vCPUs that have been provisioned on this machine
@@ -33,7 +31,7 @@ import com.atlarge.opendc.compute.virt.service.HypervisorView
* @param reversed A flag to reverse the order of the policy, such that the machine with the most provisioned cores
* is selected.
*/
-class ProvisionedCoresAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
+public class ProvisionedCoresAllocationPolicy(private val reversed: Boolean = false) : AllocationPolicy {
override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
override val comparator: Comparator<HypervisorView> =
compareBy<HypervisorView> { it.provisionedCores / it.server.flavor.cpuCount }
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/RandomAllocationPolicy.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/RandomAllocationPolicy.kt
index 07dcf1c5..ac34f410 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/RandomAllocationPolicy.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/RandomAllocationPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,26 +20,25 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt.service.allocation
+package org.opendc.compute.simulator.allocation
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
+import org.opendc.compute.simulator.HypervisorView
+import org.opendc.compute.simulator.SimVirtProvisioningService
import kotlin.random.Random
/**
* An [AllocationPolicy] that select a random node on which the server fits.
*/
-public class RandomAllocationPolicy(val random: Random = Random(0)) : AllocationPolicy {
+public class RandomAllocationPolicy(private val random: Random = Random(0)) : AllocationPolicy {
@OptIn(ExperimentalStdlibApi::class)
override fun invoke(): AllocationPolicy.Logic = object : AllocationPolicy.Logic {
override fun select(
hypervisors: Set<HypervisorView>,
- image: SimpleVirtProvisioningService.ImageView
+ image: SimVirtProvisioningService.ImageView
): HypervisorView? {
return hypervisors.asIterable()
.filter { hv ->
- val fitsMemory = hv.availableMemory >= (image.image as VmImage).requiredMemory
+ val fitsMemory = hv.availableMemory >= (image.image.tags["required-memory"] as Long)
val fitsCpu = hv.server.flavor.cpuCount >= image.flavor.cpuCount
fitsMemory && fitsCpu
}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ReplayAllocationPolicy.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ReplayAllocationPolicy.kt
new file mode 100644
index 00000000..5312f4da
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/allocation/ReplayAllocationPolicy.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.allocation
+
+import mu.KotlinLogging
+import org.opendc.compute.simulator.HypervisorView
+import org.opendc.compute.simulator.SimVirtProvisioningService
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ * Policy replaying VM-cluster assignment.
+ *
+ * Within each cluster, the active servers on each node determine which node gets
+ * assigned the VM image.
+ */
+public class ReplayAllocationPolicy(private val vmPlacements: Map<String, String>) : AllocationPolicy {
+ override fun invoke(): AllocationPolicy.Logic = object : AllocationPolicy.Logic {
+ override fun select(
+ hypervisors: Set<HypervisorView>,
+ image: SimVirtProvisioningService.ImageView
+ ): HypervisorView? {
+ val clusterName = vmPlacements[image.name]
+ ?: throw IllegalStateException("Could not find placement data in VM placement file for VM ${image.name}")
+ val machinesInCluster = hypervisors.filter { it.server.name.contains(clusterName) }
+
+ if (machinesInCluster.isEmpty()) {
+ logger.info { "Could not find any machines belonging to cluster $clusterName for image ${image.name}, assigning randomly." }
+ return hypervisors.maxByOrNull { it.availableMemory }
+ }
+
+ return machinesInCluster.maxByOrNull { it.availableMemory }
+ ?: throw IllegalStateException("Cloud not find any machine and could not randomly assign")
+ }
+ }
+}
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/PowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt
index 51c9f379..174a510b 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/PowerModel.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.power
+package org.opendc.compute.simulator.power
import kotlinx.coroutines.flow.Flow
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/power/PowerModels.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt
index 9ddbe08e..651eba6e 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/power/PowerModels.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,11 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal.power
+package org.opendc.compute.simulator.power
-import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
-import com.atlarge.opendc.core.power.PowerModel
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import org.opendc.compute.core.metal.driver.BareMetalDriver
/**
* A power model which emits a single value.
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/Powerable.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt
index 4473a571..dcf74468 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/Powerable.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.power
+package org.opendc.compute.simulator.power
import kotlinx.coroutines.flow.Flow
@@ -33,5 +33,5 @@ public interface Powerable {
/**
* The power draw at the device's power supply in watts (W).w
*/
- val powerDraw: Flow<Double>
+ public val powerDraw: Flow<Double>
}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimBareMetalDriverTest.kt
index af9d3421..0f1bd444 100644
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimBareMetalDriverTest.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,67 +20,70 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal.driver
+package org.opendc.compute.simulator
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
-import java.util.ServiceLoader
-import java.util.UUID
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.withContext
import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
+import org.opendc.compute.core.ServerEvent
+import org.opendc.compute.core.ServerState
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
+import org.opendc.simulator.compute.workload.SimFlopsWorkload
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import java.util.UUID
+
+@OptIn(ExperimentalCoroutinesApi::class)
+internal class SimBareMetalDriverTest {
+ private lateinit var machineModel: SimMachineModel
+
+ @BeforeEach
+ fun setUp() {
+ val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
+
+ machineModel = SimMachineModel(
+ cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 2000.0) },
+ memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ )
+ }
-internal class SimpleBareMetalDriverTest {
- /**
- * A smoke test for the bare-metal driver.
- */
@Test
- fun smoke() {
+ fun testFlopsWorkload() {
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
+
var finalState: ServerState = ServerState.BUILD
- val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
- val system = provider("sim")
- val root = system.newDomain(name = "root")
- root.launch {
- val dom = root.newDomain(name = "driver")
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
- val cpus = List(4) { ProcessingUnit(cpuNode, it, 2400.0) }
- val driver = SimpleBareMetalDriver(dom, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
- val image = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1_000, 2)
+ var finalTime = 0L
+
+ testScope.launch {
+ val driver = SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
+ val image = SimWorkloadImage(UUID.randomUUID(), "<unnamed>", emptyMap(), SimFlopsWorkload(4_000, 2, utilization = 1.0))
// Batch driver commands
- withContext(dom.coroutineContext) {
+ withContext(coroutineContext) {
driver.init()
driver.setImage(image)
val server = driver.start().server!!
- driver.usage
- .onEach { println("${simulationContext.clock.millis()} $it") }
- .launchIn(this)
server.events.collect { event ->
when (event) {
is ServerEvent.StateChanged -> {
- println("${simulationContext.clock.millis()} $event")
finalState = event.server.state
+ finalTime = clock.millis()
}
}
}
}
}
- runBlocking {
- system.run()
- system.terminate()
- }
-
+ testScope.advanceUntilIdle()
assertEquals(ServerState.SHUTOFF, finalState)
+ assertEquals(1001, finalTime)
}
}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimProvisioningServiceTest.kt
index ed2256c0..def78ce7 100644
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimProvisioningServiceTest.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,42 +20,54 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.metal.service
+package org.opendc.compute.simulator
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import java.util.ServiceLoader
-import java.util.UUID
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestCoroutineScope
+import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
+import org.opendc.compute.core.metal.service.SimpleProvisioningService
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
+import org.opendc.simulator.compute.workload.SimFlopsWorkload
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import java.util.UUID
/**
* Test suite for the [SimpleProvisioningService].
*/
-internal class SimpleProvisioningServiceTest {
+@OptIn(ExperimentalCoroutinesApi::class)
+internal class SimProvisioningServiceTest {
+ private lateinit var machineModel: SimMachineModel
+
+ @BeforeEach
+ fun setUp() {
+ val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
+
+ machineModel = SimMachineModel(
+ cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 2000.0) },
+ memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ )
+ }
+
/**
* A basic smoke test.
*/
@Test
- fun smoke() {
- val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
- val system = provider("sim")
- val root = system.newDomain(name = "root")
- root.launch {
- val image = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1000, 2)
- val dom = root.newDomain("provisioner")
+ fun testSmoke() {
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
- val cpus = List(4) { ProcessingUnit(cpuNode, it, 2400.0) }
- val driver = SimpleBareMetalDriver(dom.newDomain(), UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
+ testScope.launch {
+ val image = SimWorkloadImage(UUID.randomUUID(), "<unnamed>", emptyMap(), SimFlopsWorkload(1000, 2))
+ val driver = SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
- val provisioner = SimpleProvisioningService(dom)
+ val provisioner = SimpleProvisioningService()
provisioner.create(driver)
delay(5)
val nodes = provisioner.nodes()
@@ -65,9 +75,6 @@ internal class SimpleProvisioningServiceTest {
node.server!!.events.collect { println(it) }
}
- runBlocking {
- system.run()
- system.terminate()
- }
+ testScope.advanceUntilIdle()
}
}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimVirtDriverTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimVirtDriverTest.kt
new file mode 100644
index 00000000..a0c61f29
--- /dev/null
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimVirtDriverTest.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestCoroutineScope
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertAll
+import org.opendc.compute.core.Flavor
+import org.opendc.compute.core.virt.HypervisorEvent
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
+import org.opendc.simulator.compute.workload.SimTraceWorkload
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import java.time.Clock
+import java.util.UUID
+
+/**
+ * Basic test-suite for the hypervisor.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+internal class SimVirtDriverTest {
+ private lateinit var scope: TestCoroutineScope
+ private lateinit var clock: Clock
+ private lateinit var machineModel: SimMachineModel
+
+ @BeforeEach
+ fun setUp() {
+ scope = TestCoroutineScope()
+ clock = DelayControllerClockAdapter(scope)
+
+ val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
+
+ machineModel = SimMachineModel(
+ cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
+ memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ )
+ }
+
+ /**
+ * Test overcommissioning of a hypervisor.
+ */
+ @Test
+ fun overcommission() {
+ var requestedBurst = 0L
+ var grantedBurst = 0L
+ var overcommissionedBurst = 0L
+
+ scope.launch {
+ val virtDriverWorkload = SimVirtDriverWorkload()
+ val vmm = SimWorkloadImage(UUID.randomUUID(), "vmm", emptyMap(), virtDriverWorkload)
+ val duration = 5 * 60L
+ val vmImageA = SimWorkloadImage(
+ UUID.randomUUID(),
+ "<unnamed>",
+ emptyMap(),
+ SimTraceWorkload(
+ sequenceOf(
+ SimTraceWorkload.Fragment(0, 28L * duration, duration * 1000, 28.0, 2),
+ SimTraceWorkload.Fragment(0, 3500L * duration, duration * 1000, 3500.0, 2),
+ SimTraceWorkload.Fragment(0, 0, duration * 1000, 0.0, 2),
+ SimTraceWorkload.Fragment(0, 183L * duration, duration * 1000, 183.0, 2)
+ ),
+ )
+ )
+ val vmImageB = SimWorkloadImage(
+ UUID.randomUUID(),
+ "<unnamed>",
+ emptyMap(),
+ SimTraceWorkload(
+ sequenceOf(
+ SimTraceWorkload.Fragment(0, 28L * duration, duration * 1000, 28.0, 2),
+ SimTraceWorkload.Fragment(0, 3100L * duration, duration * 1000, 3100.0, 2),
+ SimTraceWorkload.Fragment(0, 0, duration * 1000, 0.0, 2),
+ SimTraceWorkload.Fragment(0, 73L * duration, duration * 1000, 73.0, 2)
+ )
+ ),
+ )
+
+ val metalDriver =
+ SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
+
+ metalDriver.init()
+ metalDriver.setImage(vmm)
+ metalDriver.start()
+
+ delay(5)
+
+ val flavor = Flavor(2, 0)
+ val vmDriver = virtDriverWorkload.driver
+ vmDriver.events
+ .onEach { event ->
+ when (event) {
+ is HypervisorEvent.SliceFinished -> {
+ requestedBurst += event.requestedBurst
+ grantedBurst += event.grantedBurst
+ overcommissionedBurst += event.overcommissionedBurst
+ }
+ }
+ }
+ .launchIn(this)
+
+ vmDriver.spawn("a", vmImageA, flavor)
+ vmDriver.spawn("b", vmImageB, flavor)
+ }
+
+ scope.advanceUntilIdle()
+
+ assertAll(
+ { assertEquals(emptyList<Throwable>(), scope.uncaughtExceptions, "No errors") },
+ { assertEquals(2073600, requestedBurst, "Requested Burst does not match") },
+ { assertEquals(2013600, grantedBurst, "Granted Burst does not match") },
+ { assertEquals(60000, overcommissionedBurst, "Overcommissioned Burst does not match") },
+ { assertEquals(1200007, scope.currentTime) }
+ )
+ }
+}
diff --git a/simulator/opendc/opendc-core/build.gradle.kts b/simulator/opendc-core/build.gradle.kts
index 5443f056..b1c2678b 100644
--- a/simulator/opendc/opendc-core/build.gradle.kts
+++ b/simulator/opendc-core/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2017 atlarge-research
+ * Copyright (c) 2017 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-description = "Base model for topology simulation"
+description = "Base model for datacenter simulation"
/* Build configuration */
plugins {
@@ -30,8 +28,7 @@ plugins {
}
dependencies {
- implementation(kotlin("stdlib"))
- api(project(":odcsim:odcsim-api"))
+ api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Library.KOTLINX_COROUTINES}")
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Environment.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Environment.kt
index 62309bf9..a5055cff 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Environment.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Environment.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core
+package org.opendc.core
/**
* A description of a large-scale computing environment. This description includes including key size and topology
@@ -33,4 +31,4 @@ package com.atlarge.opendc.core
* @property description A small textual description about the environment that is being modeled.
* @property platforms The cloud platforms (such as AWS or GCE) in this environment.
*/
-data class Environment(val name: String, val description: String?, val platforms: List<Platform>)
+public data class Environment(val name: String, val description: String?, val platforms: List<Platform>)
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Identity.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Identity.kt
index c87e934f..252c40f5 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Identity.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Identity.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,21 +20,21 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core
+package org.opendc.core
-import java.util.UUID
+import java.util.*
/**
* An object that has a unique identity.
*/
-interface Identity {
+public interface Identity {
/**
* A unique, opaque, system-generated value, representing the object.
*/
- val uid: UUID
+ public val uid: UUID
/**
* A non-empty, human-readable string representing the object.
*/
- val name: String
+ public val name: String
}
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Platform.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Platform.kt
index 0b2437c6..5550ffed 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Platform.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Platform.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core
+package org.opendc.core
-import java.util.UUID
+import java.util.*
/**
* A representation of a cloud platform such as Amazon Web Services (AWS), Microsoft Azure or Google Cloud.
@@ -33,4 +31,4 @@ import java.util.UUID
* @property name the name of the platform.
* @property zones The availability zones available on this platform.
*/
-data class Platform(override val uid: UUID, override val name: String, val zones: List<Zone>) : Identity
+public data class Platform(override val uid: UUID, override val name: String, val zones: List<Zone>) : Identity
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/User.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/User.kt
index 6105ae9e..fc542cef 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/User.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/User.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core
+package org.opendc.core
/**
* A user of the cloud network.
*/
-interface User : Identity {
+public interface User : Identity {
/**
* The name of the user.
*/
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Zone.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Zone.kt
index d8851bcd..834f6cf2 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Zone.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/Zone.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +20,10 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core
+package org.opendc.core
-import com.atlarge.opendc.core.services.ServiceRegistry
-import java.util.UUID
+import org.opendc.core.services.ServiceRegistry
+import java.util.*
/**
* An isolated location within a topology region from which public cloud services operate, roughly equivalent to a
@@ -38,7 +36,7 @@ import java.util.UUID
* @property name The name of the zone within its platform.
* @property services The service registry containing the services of the zone.
*/
-data class Zone(
+public data class Zone(
override val uid: UUID,
override val name: String,
val services: ServiceRegistry
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/Resource.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/resource/Resource.kt
index 25a494bc..5bb2c2ce 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/Resource.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/resource/Resource.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.resource
+package org.opendc.core.resource
-import com.atlarge.opendc.core.Identity
+import org.opendc.core.Identity
/**
* Represents a generic cloud resource.
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/TagContainer.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/resource/TagContainer.kt
index 6ba1cf0b..6a4ff102 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/TagContainer.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/resource/TagContainer.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,15 +20,15 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.resource
+package org.opendc.core.resource
/**
* An immutable map containing the tags of some resource.
*/
-typealias TagContainer = Map<String, Any>
+public typealias TagContainer = Map<String, Any>
/**
* Obtain the value of the tag with the specified [key] of type [T]. If the tag does not exist or the tag is of
* different type, `null` is returned.
*/
-inline fun <reified T : Any> TagContainer.typed(key: String): T? = this[key] as? T
+public inline fun <reified T : Any> TagContainer.typed(key: String): T? = this[key] as? T
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceKey.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceKey.kt
index 290bf439..9078ecdd 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceKey.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceKey.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.services
+package org.opendc.core.services
-import com.atlarge.opendc.core.Identity
-import java.util.UUID
+import org.opendc.core.Identity
+import java.util.*
/**
* An interface for identifying service implementations of the same type (providing the same service).
*
* @param T The shape of the messages the service responds to.
*/
-interface ServiceKey<T : Any> : Identity
+public interface ServiceKey<T : Any> : Identity
/**
* Helper class for constructing a [ServiceKey].
@@ -40,7 +38,7 @@ interface ServiceKey<T : Any> : Identity
* @property uid The unique identifier of the service.
* @property name The name of the service.
*/
-abstract class AbstractServiceKey<T : Any>(override val uid: UUID, override val name: String) : ServiceKey<T> {
+public abstract class AbstractServiceKey<T : Any>(override val uid: UUID, override val name: String) : ServiceKey<T> {
override fun equals(other: Any?): Boolean = other is ServiceKey<*> && uid == other.uid
override fun hashCode(): Int = uid.hashCode()
override fun toString(): String = "ServiceKey[uid=$uid, name=$name]"
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistry.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceRegistry.kt
index 75aa778f..7434d91c 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistry.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceRegistry.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.services
+package org.opendc.core.services
/**
* An immutable service registry interface.
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistryImpl.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceRegistryImpl.kt
index 0686ebaf..e117bec6 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistryImpl.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/services/ServiceRegistryImpl.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.services
+package org.opendc.core.services
/**
* Default implementation of the [ServiceRegistry] interface.
@@ -38,7 +36,8 @@ internal class ServiceRegistryImpl(private val map: Map<ServiceKey<*>, Any>) : S
return map[key] as T
}
- override fun <T : Any> put(key: ServiceKey<T>, service: T): ServiceRegistry = ServiceRegistryImpl(map.plus(key to service))
+ override fun <T : Any> put(key: ServiceKey<T>, service: T): ServiceRegistry =
+ ServiceRegistryImpl(map.plus(key to service))
override fun toString(): String = map.toString()
}
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/workload/Workload.kt b/simulator/opendc-core/src/main/kotlin/org/opendc/core/workload/Workload.kt
index def5d6e4..f0bd1137 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/workload/Workload.kt
+++ b/simulator/opendc-core/src/main/kotlin/org/opendc/core/workload/Workload.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.workload
+package org.opendc.core.workload
-import com.atlarge.opendc.core.Identity
-import com.atlarge.opendc.core.User
+import org.opendc.core.Identity
+import org.opendc.core.User
/**
* A high-level abstraction that represents the actual work that a set of compute resources perform, such
* as running an application on a machine or a whole workflow running multiple tasks on numerous machines.
*/
-interface Workload : Identity {
+public interface Workload : Identity {
/**
* The owner of this workload.
*/
- val owner: User
+ public val owner: User
}
diff --git a/simulator/odcsim/build.gradle.kts b/simulator/opendc-experiments/build.gradle.kts
index cc3f3add..a1a751a2 100644
--- a/simulator/odcsim/build.gradle.kts
+++ b/simulator/opendc-experiments/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/simulator/opendc/opendc-experiments-sc18/build.gradle.kts b/simulator/opendc-experiments/opendc-experiments-sc18/build.gradle.kts
index 2e366a43..9cf72f18 100644
--- a/simulator/opendc/opendc-experiments-sc18/build.gradle.kts
+++ b/simulator/opendc-experiments/opendc-experiments-sc18/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2019 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,16 +29,19 @@ plugins {
}
application {
- mainClassName = "com.atlarge.opendc.experiments.sc18.TestExperiment"
+ mainClassName = "org.opendc.experiments.sc18.TestExperiment"
}
dependencies {
- api(project(":opendc:opendc-core"))
- implementation(project(":opendc:opendc-format"))
- implementation(project(":opendc:opendc-workflows"))
- implementation(kotlin("stdlib"))
+ api(project(":opendc-core"))
+ implementation(project(":opendc-format"))
+ implementation(project(":opendc-workflows"))
+ implementation(project(":opendc-simulator:opendc-simulator-core"))
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8") {
+ exclude("org.jetbrains.kotlin", module = "kotlin-reflect")
+ }
+ implementation(kotlin("reflect"))
- runtimeOnly(project(":odcsim:odcsim-engine-omega"))
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
testImplementation("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}")
diff --git a/simulator/opendc/opendc-experiments-sc18/src/main/kotlin/com/atlarge/opendc/experiments/sc18/TestExperiment.kt b/simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/TestExperiment.kt
index 7659b18e..3786eebf 100644
--- a/simulator/opendc/opendc-experiments-sc18/src/main/kotlin/com/atlarge/opendc/experiments/sc18/TestExperiment.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/TestExperiment.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,37 +20,34 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc18
+package org.opendc.experiments.sc18
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.format.environment.sc18.Sc18EnvironmentReader
-import com.atlarge.opendc.format.trace.gwf.GwfTraceReader
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.WorkflowEvent
-import com.atlarge.opendc.workflows.service.WorkflowSchedulerMode
-import com.atlarge.opendc.workflows.service.stage.job.NullJobAdmissionPolicy
-import com.atlarge.opendc.workflows.service.stage.job.SubmissionTimeJobOrderPolicy
-import com.atlarge.opendc.workflows.service.stage.resource.FirstFitResourceSelectionPolicy
-import com.atlarge.opendc.workflows.service.stage.resource.FunctionalResourceFilterPolicy
-import com.atlarge.opendc.workflows.service.stage.task.NullTaskEligibilityPolicy
-import com.atlarge.opendc.workflows.service.stage.task.SubmissionTimeTaskOrderPolicy
-import java.io.File
-import java.util.ServiceLoader
-import kotlin.math.max
-import kotlinx.coroutines.async
+import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestCoroutineScope
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.format.environment.sc18.Sc18EnvironmentReader
+import org.opendc.format.trace.gwf.GwfTraceReader
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.WorkflowEvent
+import org.opendc.workflows.service.WorkflowSchedulerMode
+import org.opendc.workflows.service.stage.job.NullJobAdmissionPolicy
+import org.opendc.workflows.service.stage.job.SubmissionTimeJobOrderPolicy
+import org.opendc.workflows.service.stage.resource.FirstFitResourceSelectionPolicy
+import org.opendc.workflows.service.stage.resource.FunctionalResourceFilterPolicy
+import org.opendc.workflows.service.stage.task.NullTaskEligibilityPolicy
+import org.opendc.workflows.service.stage.task.SubmissionTimeTaskOrderPolicy
+import java.io.File
+import kotlin.math.max
/**
* Main entry point of the experiment.
*/
-fun main(args: Array<String>) {
+@OptIn(ExperimentalCoroutinesApi::class)
+public fun main(args: Array<String>) {
if (args.isEmpty()) {
println("error: Please provide path to GWF trace")
return
@@ -62,16 +57,16 @@ fun main(args: Array<String>) {
var finished = 0
val token = Channel<Boolean>()
- val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
- val system = provider(name = "sim")
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
- val schedulerDomain = system.newDomain(name = "scheduler")
- val schedulerAsync = schedulerDomain.async {
+ val schedulerAsync = testScope.async {
val environment = Sc18EnvironmentReader(object {}.javaClass.getResourceAsStream("/env/setup-test.json"))
- .use { it.construct(system.newDomain("topology")) }
+ .use { it.construct(this, clock) }
StageWorkflowService(
- schedulerDomain,
+ this,
+ clock,
environment.platforms[0].zones[0].services[ProvisioningService],
mode = WorkflowSchedulerMode.Batch(100),
jobAdmissionPolicy = NullJobAdmissionPolicy,
@@ -83,9 +78,7 @@ fun main(args: Array<String>) {
)
}
- val broker = system.newDomain(name = "broker")
-
- broker.launch {
+ testScope.launch {
val scheduler = schedulerAsync.await()
scheduler.events
.onEach { event ->
@@ -105,21 +98,18 @@ fun main(args: Array<String>) {
}
.collect()
}
- broker.launch {
- val ctx = simulationContext
+
+ testScope.launch {
val reader = GwfTraceReader(File(args[0]))
val scheduler = schedulerAsync.await()
while (reader.hasNext()) {
val (time, job) = reader.next()
total += 1
- delay(max(0, time * 1000 - ctx.clock.millis()))
+ delay(max(0, time * 1000 - clock.millis()))
scheduler.submit(job)
}
}
- runBlocking {
- system.run()
- system.terminate()
- }
+ testScope.advanceUntilIdle()
}
diff --git a/simulator/opendc/opendc-experiments-sc18/src/main/resources/env/setup-test.json b/simulator/opendc-experiments/opendc-experiments-sc18/src/main/resources/env/setup-test.json
index 0965b250..0965b250 100644
--- a/simulator/opendc/opendc-experiments-sc18/src/main/resources/env/setup-test.json
+++ b/simulator/opendc-experiments/opendc-experiments-sc18/src/main/resources/env/setup-test.json
diff --git a/simulator/opendc/opendc-experiments-sc20/build.gradle.kts b/simulator/opendc-experiments/opendc-experiments-sc20/build.gradle.kts
index 46d99564..3b682668 100644
--- a/simulator/opendc/opendc-experiments-sc20/build.gradle.kts
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2019 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,14 +29,17 @@ plugins {
}
application {
- mainClassName = "com.atlarge.opendc.experiments.sc20.MainKt"
+ mainClassName = "org.opendc.experiments.sc20.MainKt"
applicationDefaultJvmArgs = listOf("-Xms2500M")
}
dependencies {
- api(project(":opendc:opendc-core"))
- implementation(project(":opendc:opendc-format"))
- implementation(kotlin("stdlib"))
+ api(project(":opendc-core"))
+ implementation(project(":opendc-format"))
+ implementation(project(":opendc-simulator:opendc-simulator-core"))
+ implementation(project(":opendc-simulator:opendc-simulator-compute"))
+ implementation(project(":opendc-simulator:opendc-simulator-failures"))
+ implementation(project(":opendc-compute:opendc-compute-simulator"))
implementation("com.github.ajalt:clikt:2.6.0")
implementation("me.tongfei:progressbar:0.8.1")
@@ -51,7 +52,6 @@ dependencies {
}
runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:2.13.1")
- runtimeOnly(project(":odcsim:odcsim-engine-omega"))
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Main.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/Main.kt
index 4781f335..8916261b 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Main.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/Main.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,15 +20,8 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20
+package org.opendc.experiments.sc20
-import com.atlarge.opendc.experiments.sc20.experiment.*
-import com.atlarge.opendc.experiments.sc20.reporter.ConsoleExperimentReporter
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
-import com.atlarge.opendc.experiments.sc20.runner.execution.ThreadPoolExperimentScheduler
-import com.atlarge.opendc.experiments.sc20.runner.internal.DefaultExperimentRunner
-import com.atlarge.opendc.format.trace.sc20.Sc20PerformanceInterferenceReader
-import com.atlarge.opendc.format.trace.sc20.Sc20VmPlacementReader
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.convert
import com.github.ajalt.clikt.parameters.options.default
@@ -41,9 +32,15 @@ import com.github.ajalt.clikt.parameters.options.required
import com.github.ajalt.clikt.parameters.types.choice
import com.github.ajalt.clikt.parameters.types.file
import com.github.ajalt.clikt.parameters.types.int
-import java.io.File
-import java.io.InputStream
import mu.KotlinLogging
+import org.opendc.experiments.sc20.experiment.*
+import org.opendc.experiments.sc20.reporter.ConsoleExperimentReporter
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
+import org.opendc.experiments.sc20.runner.execution.ThreadPoolExperimentScheduler
+import org.opendc.experiments.sc20.runner.internal.DefaultExperimentRunner
+import org.opendc.format.trace.sc20.Sc20PerformanceInterferenceReader
+import org.opendc.format.trace.sc20.Sc20VmPlacementReader
+import java.io.File
/**
* The logger for this experiment.
@@ -53,7 +50,7 @@ private val logger = KotlinLogging.logger {}
/**
* Represents the command for running the experiment.
*/
-class ExperimentCli : CliktCommand(name = "sc20-experiment") {
+public class ExperimentCli : CliktCommand(name = "sc20-experiment") {
/**
* The path to the directory where the topology descriptions are located.
*/
@@ -71,15 +68,18 @@ class ExperimentCli : CliktCommand(name = "sc20-experiment") {
/**
* The path to the performance interference model.
*/
- private val performanceInterferenceStream by option("--performance-interference-model", help = "path to the performance interference file")
- .file()
- .convert { it.inputStream() as InputStream }
+ private val performanceInterferenceStream by option(
+ "--performance-interference-model",
+ help = "path to the performance interference file"
+ )
+ .file(canBeDir = false)
+ .convert { it.inputStream() }
/**
* The path to the original VM placements file.
*/
private val vmPlacements by option("--vm-placements-file", help = "path to the VM placement file")
- .file()
+ .file(canBeDir = false)
.convert {
Sc20VmPlacementReader(it.inputStream().buffered()).construct()
}
@@ -88,7 +88,7 @@ class ExperimentCli : CliktCommand(name = "sc20-experiment") {
/**
* The selected portfolios to run.
*/
- private val portfolios by option("--portfolio")
+ private val portfolios by option("--portfolio", help = "portfolio of scenarios to explore")
.choice(
"hor-ver" to { experiment: Experiment, i: Int -> HorVerPortfolio(experiment, i) }
as (Experiment, Int) -> Portfolio,
@@ -100,12 +100,12 @@ class ExperimentCli : CliktCommand(name = "sc20-experiment") {
"more-hpc" to { experiment, i -> MoreHpcPortfolio(experiment, i) },
ignoreCase = true
)
- .multiple()
+ .multiple(required = true)
/**
* The maximum number of worker threads to use.
*/
- private val parallelism by option("--parallelism")
+ private val parallelism by option("--parallelism", help = "maximum number of concurrent simulation runs")
.int()
.default(Runtime.getRuntime().availableProcessors())
@@ -130,7 +130,8 @@ class ExperimentCli : CliktCommand(name = "sc20-experiment") {
performanceInterferenceStream?.let { Sc20PerformanceInterferenceReader(it) }
logger.info { "Creating experiment descriptor" }
- val descriptor = object : Experiment(environmentPath, tracePath, output, performanceInterferenceModel, vmPlacements, bufferSize) {
+ val descriptor = object :
+ Experiment(environmentPath, tracePath, output, performanceInterferenceModel, vmPlacements, bufferSize) {
private val descriptor = this
override val children: Sequence<ExperimentDescriptor> = sequence {
for ((i, producer) in portfolios.withIndex()) {
@@ -142,10 +143,12 @@ class ExperimentCli : CliktCommand(name = "sc20-experiment") {
logger.info { "Starting experiment runner [parallelism=$parallelism]" }
val scheduler = ThreadPoolExperimentScheduler(parallelism)
val runner = DefaultExperimentRunner(scheduler)
+ val reporter = ConsoleExperimentReporter()
try {
- runner.execute(descriptor, ConsoleExperimentReporter())
+ runner.execute(descriptor, reporter)
} finally {
scheduler.close()
+ reporter.close()
}
}
}
@@ -153,4 +156,4 @@ class ExperimentCli : CliktCommand(name = "sc20-experiment") {
/**
* Main entry point of the experiment.
*/
-fun main(args: Array<String>) = ExperimentCli().main(args)
+public fun main(args: Array<String>): Unit = ExperimentCli().main(args)
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Experiment.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Experiment.kt
index f3ac2554..34d7301b 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Experiment.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Experiment.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,15 +20,15 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment
+package org.opendc.experiments.sc20.experiment
-import com.atlarge.opendc.experiments.sc20.runner.ContainerExperimentDescriptor
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
-import com.atlarge.opendc.experiments.sc20.telemetry.RunEvent
-import com.atlarge.opendc.experiments.sc20.telemetry.parquet.ParquetRunEventWriter
-import com.atlarge.opendc.format.trace.PerformanceInterferenceModelReader
+import org.opendc.experiments.sc20.runner.ContainerExperimentDescriptor
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
+import org.opendc.experiments.sc20.telemetry.RunEvent
+import org.opendc.experiments.sc20.telemetry.parquet.ParquetRunEventWriter
+import org.opendc.format.trace.PerformanceInterferenceModelReader
import java.io.File
/**
@@ -44,12 +42,12 @@ import java.io.File
* @param bufferSize The buffer size of the event reporters.
*/
public abstract class Experiment(
- val environments: File,
- val traces: File,
- val output: File,
- val performanceInterferenceModel: PerformanceInterferenceModelReader?,
- val vmPlacements: Map<String, String>,
- val bufferSize: Int
+ public val environments: File,
+ public val traces: File,
+ public val output: File,
+ public val performanceInterferenceModel: PerformanceInterferenceModelReader?,
+ public val vmPlacements: Map<String, String>,
+ public val bufferSize: Int
) : ContainerExperimentDescriptor() {
override val parent: ExperimentDescriptor? = null
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/ExperimentHelpers.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/ExperimentHelpers.kt
index b09c0dbb..09f44199 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/ExperimentHelpers.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/ExperimentHelpers.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,33 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment
-
-import com.atlarge.odcsim.Domain
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.compute.metal.NODE_CLUSTER
-import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.compute.virt.HypervisorEvent
-import com.atlarge.opendc.compute.virt.driver.SimpleVirtDriver
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-import com.atlarge.opendc.compute.virt.service.VirtProvisioningEvent
-import com.atlarge.opendc.compute.virt.service.allocation.AllocationPolicy
-import com.atlarge.opendc.core.failure.CorrelatedFaultInjector
-import com.atlarge.opendc.core.failure.FailureDomain
-import com.atlarge.opendc.core.failure.FaultInjector
-import com.atlarge.opendc.experiments.sc20.experiment.monitor.ExperimentMonitor
-import com.atlarge.opendc.experiments.sc20.trace.Sc20StreamingParquetTraceReader
-import com.atlarge.opendc.format.environment.EnvironmentReader
-import com.atlarge.opendc.format.trace.TraceReader
-import java.io.File
-import kotlin.math.ln
-import kotlin.math.max
-import kotlin.random.Random
+package org.opendc.experiments.sc20.experiment
+
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
@@ -57,8 +31,32 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
import mu.KotlinLogging
+import org.opendc.compute.core.Flavor
+import org.opendc.compute.core.ServerEvent
+import org.opendc.compute.core.metal.NODE_CLUSTER
+import org.opendc.compute.core.metal.driver.BareMetalDriver
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.compute.core.virt.HypervisorEvent
+import org.opendc.compute.core.virt.service.VirtProvisioningEvent
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimBareMetalDriver
+import org.opendc.compute.simulator.SimVirtDriver
+import org.opendc.compute.simulator.SimVirtProvisioningService
+import org.opendc.compute.simulator.allocation.AllocationPolicy
+import org.opendc.experiments.sc20.experiment.monitor.ExperimentMonitor
+import org.opendc.experiments.sc20.trace.Sc20StreamingParquetTraceReader
+import org.opendc.format.environment.EnvironmentReader
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
+import org.opendc.simulator.failures.CorrelatedFaultInjector
+import org.opendc.simulator.failures.FailureDomain
+import org.opendc.simulator.failures.FaultInjector
+import java.io.File
+import java.time.Clock
+import kotlin.math.ln
+import kotlin.math.max
+import kotlin.random.Random
/**
* The logger for this experiment.
@@ -68,15 +66,15 @@ private val logger = KotlinLogging.logger {}
/**
* Construct the failure domain for the experiments.
*/
-suspend fun createFailureDomain(
+public suspend fun createFailureDomain(
+ coroutineScope: CoroutineScope,
+ clock: Clock,
seed: Int,
failureInterval: Double,
bareMetalProvisioner: ProvisioningService,
chan: Channel<Unit>
-): Domain {
- val root = simulationContext.domain
- val domain = root.newDomain(name = "failures")
- domain.launch {
+): CoroutineScope {
+ val job = coroutineScope.launch {
chan.receive()
val random = Random(seed)
val injectors = mutableMapOf<String, FaultInjector>()
@@ -85,7 +83,8 @@ suspend fun createFailureDomain(
val injector =
injectors.getOrPut(cluster) {
createFaultInjector(
- simulationContext.domain,
+ this,
+ clock,
random,
failureInterval
)
@@ -93,17 +92,23 @@ suspend fun createFailureDomain(
injector.enqueue(node.metadata["driver"] as FailureDomain)
}
}
- return domain
+ return CoroutineScope(coroutineScope.coroutineContext + job)
}
/**
* Obtain the [FaultInjector] to use for the experiments.
*/
-fun createFaultInjector(domain: Domain, random: Random, failureInterval: Double): FaultInjector {
+public fun createFaultInjector(
+ coroutineScope: CoroutineScope,
+ clock: Clock,
+ random: Random,
+ failureInterval: Double
+): FaultInjector {
// Parameters from A. Iosup, A Framework for the Study of Grid Inter-Operation Mechanisms, 2009
// GRID'5000
return CorrelatedFaultInjector(
- domain,
+ coroutineScope,
+ clock,
iatScale = ln(failureInterval), iatShape = 1.03, // Hours
sizeScale = ln(2.0), sizeShape = ln(1.0), // Expect 2 machines, with variation of 1
dScale = ln(60.0), dShape = ln(60.0 * 8), // Minutes
@@ -114,7 +119,12 @@ fun createFaultInjector(domain: Domain, random: Random, failureInterval: Double)
/**
* Create the trace reader from which the VM workloads are read.
*/
-fun createTraceReader(path: File, performanceInterferenceModel: PerformanceInterferenceModel, vms: List<String>, seed: Int): Sc20StreamingParquetTraceReader {
+public fun createTraceReader(
+ path: File,
+ performanceInterferenceModel: PerformanceInterferenceModel,
+ vms: List<String>,
+ seed: Int
+): Sc20StreamingParquetTraceReader {
return Sc20StreamingParquetTraceReader(
path,
performanceInterferenceModel,
@@ -126,39 +136,45 @@ fun createTraceReader(path: File, performanceInterferenceModel: PerformanceInter
/**
* Construct the environment for a VM provisioner and return the provisioner instance.
*/
-suspend fun createProvisioner(
- root: Domain,
+public suspend fun createProvisioner(
+ coroutineScope: CoroutineScope,
+ clock: Clock,
environmentReader: EnvironmentReader,
allocationPolicy: AllocationPolicy
-): Pair<ProvisioningService, SimpleVirtProvisioningService> = withContext(root.coroutineContext) {
- val environment = environmentReader.use { it.construct(root) }
+): Pair<ProvisioningService, SimVirtProvisioningService> {
+ val environment = environmentReader.use { it.construct(coroutineScope, clock) }
val bareMetalProvisioner = environment.platforms[0].zones[0].services[ProvisioningService]
// Wait for the bare metal nodes to be spawned
delay(10)
- val scheduler = SimpleVirtProvisioningService(allocationPolicy, simulationContext, bareMetalProvisioner)
+ val scheduler = SimVirtProvisioningService(coroutineScope, clock, bareMetalProvisioner, allocationPolicy)
// Wait for the hypervisors to be spawned
delay(10)
- bareMetalProvisioner to scheduler
+ return bareMetalProvisioner to scheduler
}
/**
* Attach the specified monitor to the VM provisioner.
*/
@OptIn(ExperimentalCoroutinesApi::class)
-suspend fun attachMonitor(scheduler: SimpleVirtProvisioningService, monitor: ExperimentMonitor) {
- val domain = simulationContext.domain
- val clock = simulationContext.clock
+public suspend fun attachMonitor(
+ coroutineScope: CoroutineScope,
+ clock: Clock,
+ scheduler: SimVirtProvisioningService,
+ monitor: ExperimentMonitor
+) {
+
val hypervisors = scheduler.drivers()
// Monitor hypervisor events
for (hypervisor in hypervisors) {
// TODO Do not expose VirtDriver directly but use Hypervisor class.
- monitor.reportHostStateChange(clock.millis(), hypervisor, (hypervisor as SimpleVirtDriver).server)
- hypervisor.server.events
+ val server = (hypervisor as SimVirtDriver).server
+ monitor.reportHostStateChange(clock.millis(), hypervisor, server)
+ server.events
.onEach { event ->
val time = clock.millis()
when (event) {
@@ -167,7 +183,7 @@ suspend fun attachMonitor(scheduler: SimpleVirtProvisioningService, monitor: Exp
}
}
}
- .launchIn(domain)
+ .launchIn(coroutineScope)
hypervisor.events
.onEach { event ->
when (event) {
@@ -184,12 +200,12 @@ suspend fun attachMonitor(scheduler: SimpleVirtProvisioningService, monitor: Exp
)
}
}
- .launchIn(domain)
+ .launchIn(coroutineScope)
- val driver = hypervisor.server.services[BareMetalDriver.Key]
+ val driver = hypervisor.server.services[BareMetalDriver.Key] as SimBareMetalDriver
driver.powerDraw
.onEach { monitor.reportPowerConsumption(hypervisor.server, it) }
- .launchIn(domain)
+ .launchIn(coroutineScope)
}
scheduler.events
@@ -199,15 +215,20 @@ suspend fun attachMonitor(scheduler: SimpleVirtProvisioningService, monitor: Exp
monitor.reportProvisionerMetrics(clock.millis(), event)
}
}
- .launchIn(domain)
+ .launchIn(coroutineScope)
}
/**
* Process the trace.
*/
-suspend fun processTrace(reader: TraceReader<VmWorkload>, scheduler: SimpleVirtProvisioningService, chan: Channel<Unit>, monitor: ExperimentMonitor, vmPlacements: Map<String, String> = emptyMap()) {
- val domain = simulationContext.domain
-
+public suspend fun processTrace(
+ coroutineScope: CoroutineScope,
+ clock: Clock,
+ reader: TraceReader<VmWorkload>,
+ scheduler: SimVirtProvisioningService,
+ chan: Channel<Unit>,
+ monitor: ExperimentMonitor
+) {
try {
var submitted = 0
@@ -215,18 +236,22 @@ suspend fun processTrace(reader: TraceReader<VmWorkload>, scheduler: SimpleVirtP
val (time, workload) = reader.next()
submitted++
- delay(max(0, time - simulationContext.clock.millis()))
- domain.launch {
+ delay(max(0, time - clock.millis()))
+ coroutineScope.launch {
chan.send(Unit)
val server = scheduler.deploy(
- workload.image.name, workload.image,
- Flavor(workload.image.maxCores, workload.image.requiredMemory)
+ workload.image.name,
+ workload.image,
+ Flavor(
+ workload.image.tags["cores"] as Int,
+ workload.image.tags["required-memory"] as Long
+ )
)
// Monitor server events
server.events
.onEach {
if (it is ServerEvent.StateChanged) {
- monitor.reportVmStateChange(simulationContext.clock.millis(), it.server)
+ monitor.reportVmStateChange(clock.millis(), it.server)
}
}
.collect()
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolio.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Portfolio.kt
index 6a40f5fb..37cf2880 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolio.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Portfolio.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +20,20 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment
+package org.opendc.experiments.sc20.experiment
-import com.atlarge.opendc.experiments.sc20.experiment.model.OperationalPhenomena
-import com.atlarge.opendc.experiments.sc20.experiment.model.Topology
-import com.atlarge.opendc.experiments.sc20.experiment.model.Workload
-import com.atlarge.opendc.experiments.sc20.runner.ContainerExperimentDescriptor
+import org.opendc.experiments.sc20.experiment.model.OperationalPhenomena
+import org.opendc.experiments.sc20.experiment.model.Topology
+import org.opendc.experiments.sc20.experiment.model.Workload
+import org.opendc.experiments.sc20.runner.ContainerExperimentDescriptor
/**
* A portfolio represents a collection of scenarios are tested.
*/
public abstract class Portfolio(
override val parent: Experiment,
- val id: Int,
- val name: String
+ public val id: Int,
+ public val name: String
) : ContainerExperimentDescriptor() {
/**
* The topologies to consider.
@@ -60,7 +58,7 @@ public abstract class Portfolio(
/**
* The number of repetitions to perform.
*/
- open val repetitions: Int = 32
+ public open val repetitions: Int = 32
/**
* Resolve the children of this container.
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolios.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Portfolios.kt
index 09a6ce40..249a63b9 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Portfolios.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Portfolios.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment
+package org.opendc.experiments.sc20.experiment
-import com.atlarge.opendc.experiments.sc20.experiment.model.*
+import org.opendc.experiments.sc20.experiment.model.*
public class HorVerPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id, "horizontal_vs_vertical") {
- override val topologies = listOf(
+ override val topologies: List<Topology> = listOf(
Topology("base"),
Topology("rep-vol-hor-hom"),
Topology("rep-vol-hor-het"),
@@ -39,24 +37,24 @@ public class HorVerPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id
Topology("exp-vol-ver-het")
)
- override val workloads = listOf(
+ override val workloads: List<Workload> = listOf(
Workload("solvinity", 0.1),
Workload("solvinity", 0.25),
Workload("solvinity", 0.5),
Workload("solvinity", 1.0)
)
- override val operationalPhenomenas = listOf(
+ override val operationalPhenomenas: List<OperationalPhenomena> = listOf(
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
)
- override val allocationPolicies = listOf(
+ override val allocationPolicies: List<String> = listOf(
"active-servers"
)
}
public class MoreVelocityPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id, "more_velocity") {
- override val topologies = listOf(
+ override val topologies: List<Topology> = listOf(
Topology("base"),
Topology("rep-vel-ver-hom"),
Topology("rep-vel-ver-het"),
@@ -64,18 +62,18 @@ public class MoreVelocityPortfolio(parent: Experiment, id: Int) : Portfolio(pare
Topology("exp-vel-ver-het")
)
- override val workloads = listOf(
+ override val workloads: List<Workload> = listOf(
Workload("solvinity", 0.1),
Workload("solvinity", 0.25),
Workload("solvinity", 0.5),
Workload("solvinity", 1.0)
)
- override val operationalPhenomenas = listOf(
+ override val operationalPhenomenas: List<OperationalPhenomena> = listOf(
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
)
- override val allocationPolicies = listOf(
+ override val allocationPolicies: List<String> = listOf(
"active-servers"
)
}
@@ -83,14 +81,14 @@ public class MoreVelocityPortfolio(parent: Experiment, id: Int) : Portfolio(pare
public class CompositeWorkloadPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id, "composite-workload") {
private val totalSampleLoad = 1.3301733005049648E12
- override val topologies = listOf(
+ override val topologies: List<Topology> = listOf(
Topology("base"),
Topology("exp-vol-hor-hom"),
Topology("exp-vol-ver-hom"),
Topology("exp-vel-ver-hom")
)
- override val workloads = listOf(
+ override val workloads: List<Workload> = listOf(
CompositeWorkload(
"all-azure",
listOf(Workload("solvinity-short", 0.0), Workload("azure", 1.0)),
@@ -118,35 +116,36 @@ public class CompositeWorkloadPortfolio(parent: Experiment, id: Int) : Portfolio
)
)
- override val operationalPhenomenas = listOf(
+ override val operationalPhenomenas: List<OperationalPhenomena> = listOf(
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = false)
)
- override val allocationPolicies = listOf(
+ override val allocationPolicies: List<String> = listOf(
"active-servers"
)
}
-public class OperationalPhenomenaPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id, "operational_phenomena") {
- override val topologies = listOf(
+public class OperationalPhenomenaPortfolio(parent: Experiment, id: Int) :
+ Portfolio(parent, id, "operational_phenomena") {
+ override val topologies: List<Topology> = listOf(
Topology("base")
)
- override val workloads = listOf(
+ override val workloads: List<Workload> = listOf(
Workload("solvinity", 0.1),
Workload("solvinity", 0.25),
Workload("solvinity", 0.5),
Workload("solvinity", 1.0)
)
- override val operationalPhenomenas = listOf(
+ override val operationalPhenomenas: List<OperationalPhenomena> = listOf(
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true),
OperationalPhenomena(failureFrequency = 0.0, hasInterference = true),
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = false),
OperationalPhenomena(failureFrequency = 0.0, hasInterference = false)
)
- override val allocationPolicies = listOf(
+ override val allocationPolicies: List<String> = listOf(
"mem",
"mem-inv",
"core-mem",
@@ -158,19 +157,19 @@ public class OperationalPhenomenaPortfolio(parent: Experiment, id: Int) : Portfo
}
public class ReplayPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id, "replay") {
- override val topologies = listOf(
+ override val topologies: List<Topology> = listOf(
Topology("base")
)
- override val workloads = listOf(
+ override val workloads: List<Workload> = listOf(
Workload("solvinity", 1.0)
)
- override val operationalPhenomenas = listOf(
+ override val operationalPhenomenas: List<OperationalPhenomena> = listOf(
OperationalPhenomena(failureFrequency = 0.0, hasInterference = false)
)
- override val allocationPolicies = listOf(
+ override val allocationPolicies: List<String> = listOf(
"replay",
"active-servers"
)
@@ -195,14 +194,14 @@ public class TestPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id,
}
public class MoreHpcPortfolio(parent: Experiment, id: Int) : Portfolio(parent, id, "more_hpc") {
- override val topologies = listOf(
+ override val topologies: List<Topology> = listOf(
Topology("base"),
Topology("exp-vol-hor-hom"),
Topology("exp-vol-ver-hom"),
Topology("exp-vel-ver-hom")
)
- override val workloads = listOf(
+ override val workloads: List<Workload> = listOf(
Workload("solvinity", 0.0, samplingStrategy = SamplingStrategy.HPC),
Workload("solvinity", 0.25, samplingStrategy = SamplingStrategy.HPC),
Workload("solvinity", 0.5, samplingStrategy = SamplingStrategy.HPC),
@@ -212,11 +211,11 @@ public class MoreHpcPortfolio(parent: Experiment, id: Int) : Portfolio(parent, i
Workload("solvinity", 1.0, samplingStrategy = SamplingStrategy.HPC_LOAD)
)
- override val operationalPhenomenas = listOf(
+ override val operationalPhenomenas: List<OperationalPhenomena> = listOf(
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
)
- override val allocationPolicies = listOf(
+ override val allocationPolicies: List<String> = listOf(
"active-servers"
)
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Run.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Run.kt
index 1580e4dd..660fc882 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Run.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Run.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,29 +20,25 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment
+package org.opendc.experiments.sc20.experiment
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.opendc.compute.virt.service.allocation.AvailableCoreMemoryAllocationPolicy
-import com.atlarge.opendc.compute.virt.service.allocation.AvailableMemoryAllocationPolicy
-import com.atlarge.opendc.compute.virt.service.allocation.NumberOfActiveServersAllocationPolicy
-import com.atlarge.opendc.compute.virt.service.allocation.ProvisionedCoresAllocationPolicy
-import com.atlarge.opendc.compute.virt.service.allocation.RandomAllocationPolicy
-import com.atlarge.opendc.compute.virt.service.allocation.ReplayAllocationPolicy
-import com.atlarge.opendc.experiments.sc20.experiment.model.CompositeWorkload
-import com.atlarge.opendc.experiments.sc20.experiment.monitor.ParquetExperimentMonitor
-import com.atlarge.opendc.experiments.sc20.runner.TrialExperimentDescriptor
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
-import com.atlarge.opendc.experiments.sc20.trace.Sc20ParquetTraceReader
-import com.atlarge.opendc.experiments.sc20.trace.Sc20RawParquetTraceReader
-import com.atlarge.opendc.format.environment.sc20.Sc20ClusterEnvironmentReader
-import java.io.File
-import java.util.ServiceLoader
-import kotlin.random.Random
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestCoroutineScope
import mu.KotlinLogging
+import org.opendc.compute.simulator.allocation.*
+import org.opendc.experiments.sc20.experiment.model.CompositeWorkload
+import org.opendc.experiments.sc20.experiment.monitor.ParquetExperimentMonitor
+import org.opendc.experiments.sc20.runner.TrialExperimentDescriptor
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
+import org.opendc.experiments.sc20.trace.Sc20ParquetTraceReader
+import org.opendc.experiments.sc20.trace.Sc20RawParquetTraceReader
+import org.opendc.format.environment.sc20.Sc20ClusterEnvironmentReader
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import java.io.File
+import kotlin.random.Random
/**
* The logger for the experiment scenario.
@@ -52,19 +46,15 @@ import mu.KotlinLogging
private val logger = KotlinLogging.logger {}
/**
- * The provider for the simulation engine to use.
- */
-private val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
-
-/**
* An experiment run represent a single invocation of a trial and is used to distinguish between repetitions of the
* same set of parameters.
*/
+@OptIn(ExperimentalCoroutinesApi::class)
public data class Run(override val parent: Scenario, val id: Int, val seed: Int) : TrialExperimentDescriptor() {
override suspend fun invoke(context: ExperimentExecutionContext) {
val experiment = parent.parent.parent
- val system = provider("experiment-$id")
- val root = system.newDomain("root")
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
val seeder = Random(seed)
val environment = Sc20ClusterEnvironmentReader(File(experiment.environments, "${parent.topology.name}.txt"))
@@ -112,9 +102,10 @@ public data class Run(override val parent: Scenario, val id: Int, val seed: Int)
parent.parent.parent.bufferSize
)
- root.launch {
+ testScope.launch {
val (bareMetalProvisioner, scheduler) = createProvisioner(
- root,
+ this,
+ clock,
environment,
allocationPolicy
)
@@ -122,6 +113,8 @@ public data class Run(override val parent: Scenario, val id: Int, val seed: Int)
val failureDomain = if (parent.operationalPhenomena.failureFrequency > 0) {
logger.debug("ENABLING failures")
createFailureDomain(
+ this,
+ clock,
seeder.nextInt(),
parent.operationalPhenomena.failureFrequency,
bareMetalProvisioner,
@@ -131,13 +124,14 @@ public data class Run(override val parent: Scenario, val id: Int, val seed: Int)
null
}
- attachMonitor(scheduler, monitor)
+ attachMonitor(this, clock, scheduler, monitor)
processTrace(
+ this,
+ clock,
trace,
scheduler,
chan,
- monitor,
- experiment.vmPlacements
+ monitor
)
logger.debug("SUBMIT=${scheduler.submittedVms}")
@@ -151,9 +145,8 @@ public data class Run(override val parent: Scenario, val id: Int, val seed: Int)
}
try {
- system.run()
+ testScope.advanceUntilIdle()
} finally {
- system.terminate()
monitor.close()
}
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Scenario.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Scenario.kt
index 98bc7fc2..d092ddd5 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/Scenario.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/Scenario.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,25 +20,25 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment
+package org.opendc.experiments.sc20.experiment
-import com.atlarge.opendc.experiments.sc20.experiment.model.OperationalPhenomena
-import com.atlarge.opendc.experiments.sc20.experiment.model.Topology
-import com.atlarge.opendc.experiments.sc20.experiment.model.Workload
-import com.atlarge.opendc.experiments.sc20.runner.ContainerExperimentDescriptor
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
+import org.opendc.experiments.sc20.experiment.model.OperationalPhenomena
+import org.opendc.experiments.sc20.experiment.model.Topology
+import org.opendc.experiments.sc20.experiment.model.Workload
+import org.opendc.experiments.sc20.runner.ContainerExperimentDescriptor
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
/**
* A scenario represents a single point in the design space (a unique combination of parameters).
*/
public class Scenario(
override val parent: Portfolio,
- val id: Int,
- val repetitions: Int,
- val topology: Topology,
- val workload: Workload,
- val allocationPolicy: String,
- val operationalPhenomena: OperationalPhenomena
+ public val id: Int,
+ public val repetitions: Int,
+ public val topology: Topology,
+ public val workload: Workload,
+ public val allocationPolicy: String,
+ public val operationalPhenomena: OperationalPhenomena
) : ContainerExperimentDescriptor() {
override val children: Sequence<ExperimentDescriptor> = sequence {
repeat(repetitions) { i -> yield(Run(this@Scenario, i, i)) }
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/OperationalPhenomena.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/OperationalPhenomena.kt
index af99df84..b22f4c9e 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/OperationalPhenomena.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/OperationalPhenomena.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment.model
+package org.opendc.experiments.sc20.experiment.model
/**
* Operation phenomena during experiments.
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/Topology.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/Topology.kt
index ea09688b..95062fda 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/Topology.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/Topology.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment.model
+package org.opendc.experiments.sc20.experiment.model
/**
* The topology topology on which we test the workload.
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/Workload.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/Workload.kt
index d75ca6f9..ba95f544 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/model/Workload.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/model/Workload.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment.model
+package org.opendc.experiments.sc20.experiment.model
-enum class SamplingStrategy {
+public enum class SamplingStrategy {
REGULAR,
HPC,
HPC_LOAD
@@ -33,10 +31,14 @@ enum class SamplingStrategy {
/**
* A workload that is considered for a scenario.
*/
-public open class Workload(open val name: String, val fraction: Double, val samplingStrategy: SamplingStrategy = SamplingStrategy.REGULAR)
+public open class Workload(
+ public open val name: String,
+ public val fraction: Double,
+ public val samplingStrategy: SamplingStrategy = SamplingStrategy.REGULAR
+)
/**
* A workload that is composed of multiple workloads.
*/
-public class CompositeWorkload(override val name: String, val workloads: List<Workload>, val totalLoad: Double) :
+public class CompositeWorkload(override val name: String, public val workloads: List<Workload>, public val totalLoad: Double) :
Workload(name, -1.0)
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/monitor/ExperimentMonitor.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/monitor/ExperimentMonitor.kt
index 1f674f00..18ba2c33 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/monitor/ExperimentMonitor.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/monitor/ExperimentMonitor.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,40 +20,41 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment.monitor
+package org.opendc.experiments.sc20.experiment.monitor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.compute.virt.service.VirtProvisioningEvent
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.virt.driver.VirtDriver
+import org.opendc.compute.core.virt.service.VirtProvisioningEvent
import java.io.Closeable
/**
* A monitor watches the events of an experiment.
*/
-interface ExperimentMonitor : Closeable {
+public interface ExperimentMonitor : Closeable {
/**
* This method is invoked when the state of a VM changes.
*/
- fun reportVmStateChange(time: Long, server: Server) {}
+ public fun reportVmStateChange(time: Long, server: Server) {}
/**
* This method is invoked when the state of a host changes.
*/
- fun reportHostStateChange(
+ public fun reportHostStateChange(
time: Long,
driver: VirtDriver,
server: Server
- ) {}
+ ) {
+ }
/**
* Report the power consumption of a host.
*/
- fun reportPowerConsumption(host: Server, draw: Double) {}
+ public fun reportPowerConsumption(host: Server, draw: Double) {}
/**
* This method is invoked for a host for each slice that is finishes.
*/
- fun reportHostSlice(
+ public fun reportHostSlice(
time: Long,
requestedBurst: Long,
grantedBurst: Long,
@@ -66,10 +65,11 @@ interface ExperimentMonitor : Closeable {
numberOfDeployedImages: Int,
hostServer: Server,
duration: Long = 5 * 60 * 1000L
- ) {}
+ ) {
+ }
/**
* This method is invoked for a provisioner event.
*/
- fun reportProvisionerMetrics(time: Long, event: VirtProvisioningEvent.MetricsAvailable) {}
+ public fun reportProvisionerMetrics(time: Long, event: VirtProvisioningEvent.MetricsAvailable) {}
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/monitor/ParquetExperimentMonitor.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/monitor/ParquetExperimentMonitor.kt
index b931fef9..3eb9362c 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/experiment/monitor/ParquetExperimentMonitor.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/experiment/monitor/ParquetExperimentMonitor.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.experiment.monitor
+package org.opendc.experiments.sc20.experiment.monitor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.compute.virt.service.VirtProvisioningEvent
-import com.atlarge.opendc.experiments.sc20.telemetry.HostEvent
-import com.atlarge.opendc.experiments.sc20.telemetry.ProvisionerEvent
-import com.atlarge.opendc.experiments.sc20.telemetry.parquet.ParquetHostEventWriter
-import com.atlarge.opendc.experiments.sc20.telemetry.parquet.ParquetProvisionerEventWriter
-import java.io.File
import mu.KotlinLogging
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.virt.driver.VirtDriver
+import org.opendc.compute.core.virt.service.VirtProvisioningEvent
+import org.opendc.experiments.sc20.telemetry.HostEvent
+import org.opendc.experiments.sc20.telemetry.ProvisionerEvent
+import org.opendc.experiments.sc20.telemetry.parquet.ParquetHostEventWriter
+import org.opendc.experiments.sc20.telemetry.parquet.ParquetProvisionerEventWriter
+import java.io.File
/**
* The logger instance to use.
@@ -42,7 +40,7 @@ private val logger = KotlinLogging.logger {}
/**
* An [ExperimentMonitor] that logs the events to a Parquet file.
*/
-class ParquetExperimentMonitor(base: File, partition: String, bufferSize: Int) : ExperimentMonitor {
+public class ParquetExperimentMonitor(base: File, partition: String, bufferSize: Int) : ExperimentMonitor {
private val hostWriter = ParquetHostEventWriter(
File(base, "host-metrics/$partition/data.parquet"),
bufferSize
@@ -59,7 +57,7 @@ class ParquetExperimentMonitor(base: File, partition: String, bufferSize: Int) :
startTime = time
// Update timestamp of initial event
- currentHostEvent.replaceAll { k, v -> v.copy(timestamp = startTime) }
+ currentHostEvent.replaceAll { _, v -> v.copy(timestamp = startTime) }
}
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/reporter/ConsoleExperimentReporter.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/reporter/ConsoleExperimentReporter.kt
index b446abc8..af61622a 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/reporter/ConsoleExperimentReporter.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/reporter/ConsoleExperimentReporter.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +20,20 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.reporter
+package org.opendc.experiments.sc20.reporter
-import com.atlarge.opendc.experiments.sc20.experiment.Run
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionResult
import me.tongfei.progressbar.ProgressBar
import me.tongfei.progressbar.ProgressBarBuilder
import mu.KotlinLogging
+import org.opendc.experiments.sc20.experiment.Run
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionResult
/**
* A reporter that reports the experiment progress to the console.
*/
-public class ConsoleExperimentReporter : ExperimentExecutionListener {
+public class ConsoleExperimentReporter : ExperimentExecutionListener, AutoCloseable {
/**
* The active [Run]s.
*/
@@ -82,4 +80,8 @@ public class ConsoleExperimentReporter : ExperimentExecutionListener {
}
override fun executionStarted(descriptor: ExperimentDescriptor) {}
+
+ override fun close() {
+ pb.close()
+ }
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ContainerExperimentDescriptor.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ContainerExperimentDescriptor.kt
index dac32586..d70e8c9a 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ContainerExperimentDescriptor.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ContainerExperimentDescriptor.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner
+package org.opendc.experiments.sc20.runner
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionResult
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionResult
/**
* An abstract [ExperimentDescriptor] specifically for containers.
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ExperimentDescriptor.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ExperimentDescriptor.kt
index 64b6b767..1e67c086 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ExperimentDescriptor.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ExperimentDescriptor.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner
+package org.opendc.experiments.sc20.runner
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
import java.io.Serializable
/**
@@ -43,7 +41,7 @@ public abstract class ExperimentDescriptor : Serializable {
/**
* The type of descriptor.
*/
- abstract val type: Type
+ public abstract val type: Type
/**
* A flag to indicate that this descriptor is a root descriptor.
@@ -54,7 +52,7 @@ public abstract class ExperimentDescriptor : Serializable {
/**
* A flag to indicate that this descriptor describes an experiment trial.
*/
- val isTrial: Boolean
+ public val isTrial: Boolean
get() = type == Type.TRIAL
/**
@@ -67,7 +65,7 @@ public abstract class ExperimentDescriptor : Serializable {
/**
* The types of experiment descriptors.
*/
- enum class Type {
+ public enum class Type {
/**
* A composition of multiple experiment descriptions whose invocation happens on a single thread.
*/
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ExperimentRunner.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ExperimentRunner.kt
index 77f970fe..a59481c0 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/ExperimentRunner.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/ExperimentRunner.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner
+package org.opendc.experiments.sc20.runner
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
/**
* An [ExperimentRunner] facilitates discovery and execution of experiments.
@@ -33,12 +31,12 @@ public interface ExperimentRunner {
/**
* The unique identifier of this runner.
*/
- val id: String
+ public val id: String
/**
* The version of this runner.
*/
- val version: String?
+ public val version: String?
get() = null
/**
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/TrialExperimentDescriptor.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/TrialExperimentDescriptor.kt
index cf05416a..abc52997 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/TrialExperimentDescriptor.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/TrialExperimentDescriptor.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner
+package org.opendc.experiments.sc20.runner
/**
* An abstract [ExperimentDescriptor] specifically for trials.
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionContext.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionContext.kt
index 9a04c491..942eb891 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionContext.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionContext.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner.execution
+package org.opendc.experiments.sc20.runner.execution
/**
* The execution context of an experiment.
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionListener.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionListener.kt
index f6df0524..42fef164 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionListener.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionListener.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,27 +20,27 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner.execution
+package org.opendc.experiments.sc20.runner.execution
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
/**
* Listener to be notified of experiment execution events by experiment runners.
*/
-interface ExperimentExecutionListener {
+public interface ExperimentExecutionListener {
/**
* A method that is invoked when a new [ExperimentDescriptor] is registered.
*/
- fun descriptorRegistered(descriptor: ExperimentDescriptor)
+ public fun descriptorRegistered(descriptor: ExperimentDescriptor)
/**
* A method that is invoked when when the execution of a leaf or subtree of the experiment tree has finished,
* regardless of the outcome.
*/
- fun executionFinished(descriptor: ExperimentDescriptor, result: ExperimentExecutionResult)
+ public fun executionFinished(descriptor: ExperimentDescriptor, result: ExperimentExecutionResult)
/**
* A method that is invoked when the execution of a leaf or subtree of the experiment tree is about to be started.
*/
- fun executionStarted(descriptor: ExperimentDescriptor)
+ public fun executionStarted(descriptor: ExperimentDescriptor)
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionResult.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionResult.kt
index 057e1f92..a765c264 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentExecutionResult.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentExecutionResult.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner.execution
+package org.opendc.experiments.sc20.runner.execution
import java.io.Serializable
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentScheduler.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentScheduler.kt
index 96678abf..70095ccd 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ExperimentScheduler.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ExperimentScheduler.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,27 +20,27 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner.execution
+package org.opendc.experiments.sc20.runner.execution
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
import java.io.Closeable
/**
* A interface for scheduling the execution of experiment trials over compute resources (threads/containers/vms)
*/
-interface ExperimentScheduler : Closeable {
+public interface ExperimentScheduler : Closeable {
/**
* Allocate a [Worker] for executing an experiment trial. This method may suspend in case no resources are directly
* available at the moment.
*
* @return The available worker.
*/
- suspend fun allocate(): ExperimentScheduler.Worker
+ public suspend fun allocate(): ExperimentScheduler.Worker
/**
* An isolated worker of an [ExperimentScheduler] that is responsible for executing a single experiment trial.
*/
- interface Worker {
+ public interface Worker {
/**
* Dispatch the specified [ExperimentDescriptor] to execute some time in the future and return the results of
* the trial.
@@ -50,7 +48,7 @@ interface ExperimentScheduler : Closeable {
* @param descriptor The descriptor to execute.
* @param context The context to execute the descriptor in.
*/
- suspend operator fun invoke(
+ public suspend operator fun invoke(
descriptor: ExperimentDescriptor,
context: ExperimentExecutionContext
)
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ThreadPoolExperimentScheduler.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ThreadPoolExperimentScheduler.kt
index a8ee59a8..942faed1 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/execution/ThreadPoolExperimentScheduler.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/execution/ThreadPoolExperimentScheduler.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,22 +20,22 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner.execution
+package org.opendc.experiments.sc20.runner.execution
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
-import java.util.concurrent.Executors
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.withContext
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
+import java.util.concurrent.Executors
/**
* An [ExperimentScheduler] that runs experiments using a local thread pool.
*
* @param parallelism The maximum amount of parallel workers (default is the number of available processors).
*/
-class ThreadPoolExperimentScheduler(parallelism: Int = Runtime.getRuntime().availableProcessors() + 1) : ExperimentScheduler {
+public class ThreadPoolExperimentScheduler(parallelism: Int = Runtime.getRuntime().availableProcessors() + 1) : ExperimentScheduler {
private val dispatcher = Executors.newCachedThreadPool().asCoroutineDispatcher()
private val tickets = Semaphore(parallelism)
@@ -54,7 +52,10 @@ class ThreadPoolExperimentScheduler(parallelism: Int = Runtime.getRuntime().avai
launch { context.listener.descriptorRegistered(descriptor) }
}
- override fun executionFinished(descriptor: ExperimentDescriptor, result: ExperimentExecutionResult) {
+ override fun executionFinished(
+ descriptor: ExperimentDescriptor,
+ result: ExperimentExecutionResult
+ ) {
launch { context.listener.executionFinished(descriptor, result) }
}
@@ -78,5 +79,5 @@ class ThreadPoolExperimentScheduler(parallelism: Int = Runtime.getRuntime().avai
}
}
- override fun close() = dispatcher.close()
+ override fun close(): Unit = dispatcher.close()
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/internal/DefaultExperimentRunner.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/internal/DefaultExperimentRunner.kt
index 28a19172..26e4df89 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/runner/internal/DefaultExperimentRunner.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/runner/internal/DefaultExperimentRunner.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,28 +20,28 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.runner.internal
+package org.opendc.experiments.sc20.runner.internal
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentDescriptor
-import com.atlarge.opendc.experiments.sc20.runner.ExperimentRunner
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentExecutionResult
-import com.atlarge.opendc.experiments.sc20.runner.execution.ExperimentScheduler
-import java.util.concurrent.ConcurrentHashMap
import kotlinx.coroutines.runBlocking
+import org.opendc.experiments.sc20.runner.ExperimentDescriptor
+import org.opendc.experiments.sc20.runner.ExperimentRunner
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionContext
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionListener
+import org.opendc.experiments.sc20.runner.execution.ExperimentExecutionResult
+import org.opendc.experiments.sc20.runner.execution.ExperimentScheduler
+import java.util.concurrent.ConcurrentHashMap
/**
* The default implementation of the [ExperimentRunner] interface.
*
* @param scheduler The scheduler to use.
*/
-public class DefaultExperimentRunner(val scheduler: ExperimentScheduler) : ExperimentRunner {
+public class DefaultExperimentRunner(private val scheduler: ExperimentScheduler) : ExperimentRunner {
override val id: String = "default"
override val version: String? = "1.0"
- override fun execute(root: ExperimentDescriptor, listener: ExperimentExecutionListener) = runBlocking {
+ override fun execute(root: ExperimentDescriptor, listener: ExperimentExecutionListener): Unit = runBlocking {
val context = object : ExperimentExecutionContext {
override val listener: ExperimentExecutionListener = listener
override val scheduler: ExperimentScheduler = this@DefaultExperimentRunner.scheduler
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/Event.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/Event.kt
index c1e14e2a..38a4a227 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/Event.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/Event.kt
@@ -22,12 +22,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry
+package org.opendc.experiments.sc20.telemetry
/**
* An event that occurs within the system.
*/
-public abstract class Event(val name: String) {
+public abstract class Event(public val name: String) {
/**
* The time of occurrence of this event.
*/
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/HostEvent.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/HostEvent.kt
index b9030172..042d204e 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/HostEvent.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/HostEvent.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,24 +20,24 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry
+package org.opendc.experiments.sc20.telemetry
-import com.atlarge.opendc.compute.core.Server
+import org.opendc.compute.core.Server
/**
* A periodic report of the host machine metrics.
*/
-data class HostEvent(
+public data class HostEvent(
override val timestamp: Long,
- val duration: Long,
- val host: Server,
- val vmCount: Int,
- val requestedBurst: Long,
- val grantedBurst: Long,
- val overcommissionedBurst: Long,
- val interferedBurst: Long,
- val cpuUsage: Double,
- val cpuDemand: Double,
- val powerDraw: Double,
- val cores: Int
+ public val duration: Long,
+ public val host: Server,
+ public val vmCount: Int,
+ public val requestedBurst: Long,
+ public val grantedBurst: Long,
+ public val overcommissionedBurst: Long,
+ public val interferedBurst: Long,
+ public val cpuUsage: Double,
+ public val cpuDemand: Double,
+ public val powerDraw: Double,
+ public val cores: Int
) : Event("host-metrics")
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/ProvisionerEvent.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/ProvisionerEvent.kt
index df619632..d063bc54 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/ProvisionerEvent.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/ProvisionerEvent.kt
@@ -22,18 +22,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry
+package org.opendc.experiments.sc20.telemetry
/**
* A periodic report of the provisioner's metrics.
*/
-data class ProvisionerEvent(
+public data class ProvisionerEvent(
override val timestamp: Long,
- val totalHostCount: Int,
- val availableHostCount: Int,
- val totalVmCount: Int,
- val activeVmCount: Int,
- val inactiveVmCount: Int,
- val waitingVmCount: Int,
- val failedVmCount: Int
+ public val totalHostCount: Int,
+ public val availableHostCount: Int,
+ public val totalVmCount: Int,
+ public val activeVmCount: Int,
+ public val inactiveVmCount: Int,
+ public val waitingVmCount: Int,
+ public val failedVmCount: Int
) : Event("provisioner-metrics")
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/RunEvent.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/RunEvent.kt
index 497d2c3f..3bcd10a1 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/RunEvent.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/RunEvent.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +20,14 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry
+package org.opendc.experiments.sc20.telemetry
-import com.atlarge.opendc.experiments.sc20.experiment.Run
+import org.opendc.experiments.sc20.experiment.Run
/**
* A periodic report of the host machine metrics.
*/
-data class RunEvent(
- val run: Run,
+public data class RunEvent(
+ public val run: Run,
override val timestamp: Long
) : Event("run")
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/VmEvent.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/VmEvent.kt
index 7289fb21..c18069c9 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/VmEvent.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/VmEvent.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,22 +20,22 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry
+package org.opendc.experiments.sc20.telemetry
-import com.atlarge.opendc.compute.core.Server
+import org.opendc.compute.core.Server
/**
* A periodic report of a virtual machine's metrics.
*/
-data class VmEvent(
+public data class VmEvent(
override val timestamp: Long,
- val duration: Long,
- val vm: Server,
- val host: Server,
- val requestedBurst: Long,
- val grantedBurst: Long,
- val overcommissionedBurst: Long,
- val interferedBurst: Long,
- val cpuUsage: Double,
- val cpuDemand: Double
+ public val duration: Long,
+ public val vm: Server,
+ public val host: Server,
+ public val requestedBurst: Long,
+ public val grantedBurst: Long,
+ public val overcommissionedBurst: Long,
+ public val interferedBurst: Long,
+ public val cpuUsage: Double,
+ public val cpuDemand: Double
) : Event("vm-metrics")
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetEventWriter.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetEventWriter.kt
index e42ac654..79bc23db 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetEventWriter.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetEventWriter.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +20,20 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry.parquet
+package org.opendc.experiments.sc20.telemetry.parquet
-import com.atlarge.opendc.experiments.sc20.telemetry.Event
-import java.io.Closeable
-import java.io.File
-import java.util.concurrent.ArrayBlockingQueue
-import java.util.concurrent.BlockingQueue
-import kotlin.concurrent.thread
import mu.KotlinLogging
import org.apache.avro.Schema
import org.apache.avro.generic.GenericData
import org.apache.hadoop.fs.Path
import org.apache.parquet.avro.AvroParquetWriter
import org.apache.parquet.hadoop.metadata.CompressionCodecName
+import org.opendc.experiments.sc20.telemetry.Event
+import java.io.Closeable
+import java.io.File
+import java.util.concurrent.ArrayBlockingQueue
+import java.util.concurrent.BlockingQueue
+import kotlin.concurrent.thread
/**
* The logging instance to use.
@@ -52,6 +50,16 @@ public open class ParquetEventWriter<in T : Event>(
private val bufferSize: Int = 4096
) : Runnable, Closeable {
/**
+ * The writer to write the Parquet file.
+ */
+ private val writer = AvroParquetWriter.builder<GenericData.Record>(Path(path.absolutePath))
+ .withSchema(schema)
+ .withCompressionCodec(CompressionCodecName.SNAPPY)
+ .withPageSize(4 * 1024 * 1024) // For compression
+ .withRowGroupSize(16 * 1024 * 1024) // For write buffering (Page size)
+ .build()
+
+ /**
* The queue of commands to process.
*/
private val queue: BlockingQueue<Action> = ArrayBlockingQueue(bufferSize)
@@ -59,7 +67,7 @@ public open class ParquetEventWriter<in T : Event>(
/**
* The thread that is responsible for writing the Parquet records.
*/
- private val writerThread = thread(start = true, name = "parquet-writer") { run() }
+ private val writerThread = thread(start = false, name = "parquet-writer") { run() }
/**
* Write the specified metrics to the database.
@@ -76,17 +84,14 @@ public open class ParquetEventWriter<in T : Event>(
writerThread.join()
}
+ init {
+ writerThread.start()
+ }
+
/**
* Start the writer thread.
*/
override fun run() {
- val writer = AvroParquetWriter.builder<GenericData.Record>(Path(path.absolutePath))
- .withSchema(schema)
- .withCompressionCodec(CompressionCodecName.SNAPPY)
- .withPageSize(4 * 1024 * 1024) // For compression
- .withRowGroupSize(16 * 1024 * 1024) // For write buffering (Page size)
- .build()
-
try {
loop@ while (true) {
val action = queue.take()
@@ -107,15 +112,15 @@ public open class ParquetEventWriter<in T : Event>(
}
}
- sealed class Action {
+ public sealed class Action {
/**
* A poison pill that will stop the writer thread.
*/
- object Stop : Action()
+ public object Stop : Action()
/**
* Write the specified metrics to the database.
*/
- data class Write<out T : Event>(val event: T) : Action()
+ public data class Write<out T : Event>(val event: T) : Action()
}
}
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetHostEventWriter.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetHostEventWriter.kt
index 9fa4e0fb..bd4eae37 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetHostEventWriter.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetHostEventWriter.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +20,13 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry.parquet
+package org.opendc.experiments.sc20.telemetry.parquet
-import com.atlarge.opendc.experiments.sc20.telemetry.HostEvent
-import java.io.File
import org.apache.avro.Schema
import org.apache.avro.SchemaBuilder
import org.apache.avro.generic.GenericData
+import org.opendc.experiments.sc20.telemetry.HostEvent
+import java.io.File
/**
* A Parquet event writer for [HostEvent]s.
@@ -38,8 +36,8 @@ public class ParquetHostEventWriter(path: File, bufferSize: Int) :
override fun toString(): String = "host-writer"
- companion object {
- val convert: (HostEvent, GenericData.Record) -> Unit = { event, record ->
+ public companion object {
+ private val convert: (HostEvent, GenericData.Record) -> Unit = { event, record ->
// record.put("portfolio_id", event.run.parent.parent.id)
// record.put("scenario_id", event.run.parent.id)
// record.put("run_id", event.run.id)
@@ -58,9 +56,9 @@ public class ParquetHostEventWriter(path: File, bufferSize: Int) :
record.put("cores", event.cores)
}
- val schema: Schema = SchemaBuilder
+ private val schema: Schema = SchemaBuilder
.record("host_metrics")
- .namespace("com.atlarge.opendc.experiments.sc20")
+ .namespace("org.opendc.experiments.sc20")
.fields()
// .name("portfolio_id").type().intType().noDefault()
// .name("scenario_id").type().intType().noDefault()
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetProvisionerEventWriter.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetProvisionerEventWriter.kt
index 3d28860c..5d53a7bb 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetProvisionerEventWriter.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetProvisionerEventWriter.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +20,13 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry.parquet
+package org.opendc.experiments.sc20.telemetry.parquet
-import com.atlarge.opendc.experiments.sc20.telemetry.ProvisionerEvent
-import java.io.File
import org.apache.avro.Schema
import org.apache.avro.SchemaBuilder
import org.apache.avro.generic.GenericData
+import org.opendc.experiments.sc20.telemetry.ProvisionerEvent
+import java.io.File
/**
* A Parquet event writer for [ProvisionerEvent]s.
@@ -38,8 +36,8 @@ public class ParquetProvisionerEventWriter(path: File, bufferSize: Int) :
override fun toString(): String = "provisioner-writer"
- companion object {
- val convert: (ProvisionerEvent, GenericData.Record) -> Unit = { event, record ->
+ public companion object {
+ private val convert: (ProvisionerEvent, GenericData.Record) -> Unit = { event, record ->
record.put("timestamp", event.timestamp)
record.put("host_total_count", event.totalHostCount)
record.put("host_available_count", event.availableHostCount)
@@ -50,9 +48,9 @@ public class ParquetProvisionerEventWriter(path: File, bufferSize: Int) :
record.put("vm_failed_count", event.failedVmCount)
}
- val schema: Schema = SchemaBuilder
+ private val schema: Schema = SchemaBuilder
.record("provisioner_metrics")
- .namespace("com.atlarge.opendc.experiments.sc20")
+ .namespace("org.opendc.experiments.sc20")
.fields()
.name("timestamp").type().longType().noDefault()
.name("host_total_count").type().intType().noDefault()
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt
index 043e4670..74efb660 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/telemetry/parquet/ParquetRunEventWriter.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +20,13 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.telemetry.parquet
+package org.opendc.experiments.sc20.telemetry.parquet
-import com.atlarge.opendc.experiments.sc20.telemetry.RunEvent
-import java.io.File
import org.apache.avro.Schema
import org.apache.avro.SchemaBuilder
import org.apache.avro.generic.GenericData
+import org.opendc.experiments.sc20.telemetry.RunEvent
+import java.io.File
/**
* A Parquet event writer for [RunEvent]s.
@@ -38,8 +36,8 @@ public class ParquetRunEventWriter(path: File, bufferSize: Int) :
override fun toString(): String = "run-writer"
- companion object {
- val convert: (RunEvent, GenericData.Record) -> Unit = { event, record ->
+ public companion object {
+ private val convert: (RunEvent, GenericData.Record) -> Unit = { event, record ->
val run = event.run
val scenario = run.parent
val portfolio = scenario.parent
@@ -58,9 +56,9 @@ public class ParquetRunEventWriter(path: File, bufferSize: Int) :
record.put("seed", run.seed)
}
- val schema: Schema = SchemaBuilder
+ private val schema: Schema = SchemaBuilder
.record("runs")
- .namespace("com.atlarge.opendc.experiments.sc20")
+ .namespace("org.opendc.experiments.sc20")
.fields()
.name("portfolio_id").type().intType().noDefault()
.name("portfolio_name").type().stringType().noDefault()
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20ParquetTraceReader.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20ParquetTraceReader.kt
index 06bececf..d735ea4b 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20ParquetTraceReader.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20ParquetTraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.trace
+package org.opendc.experiments.sc20.trace
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.core.workload.IMAGE_PERF_INTERFERENCE_MODEL
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.experiments.sc20.experiment.model.CompositeWorkload
-import com.atlarge.opendc.experiments.sc20.experiment.model.Workload
-import com.atlarge.opendc.format.trace.TraceEntry
-import com.atlarge.opendc.format.trace.TraceReader
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.experiments.sc20.experiment.model.CompositeWorkload
+import org.opendc.experiments.sc20.experiment.model.Workload
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.interference.IMAGE_PERF_INTERFERENCE_MODEL
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
import java.util.TreeSet
/**
@@ -42,7 +40,7 @@ import java.util.TreeSet
* @param run The run to which this reader belongs.
*/
@OptIn(ExperimentalStdlibApi::class)
-class Sc20ParquetTraceReader(
+public class Sc20ParquetTraceReader(
rawReaders: List<Sc20RawParquetTraceReader>,
performanceInterferenceModel: Map<String, PerformanceInterferenceModel>,
workload: Workload,
@@ -75,13 +73,11 @@ class Sc20ParquetTraceReader(
performanceInterferenceModel[id] ?: PerformanceInterferenceModel(TreeSet())
val newImage =
- VmImage(
+ SimWorkloadImage(
image.uid,
image.name,
- mapOf(IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems),
- image.flopsHistory,
- image.maxCores,
- image.requiredMemory
+ image.tags + mapOf(IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems),
+ (image as SimWorkloadImage).workload
)
val newWorkload = entry.workload.copy(image = newImage)
Sc20RawParquetTraceReader.TraceEntryImpl(entry.submissionTime, newWorkload)
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20RawParquetTraceReader.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20RawParquetTraceReader.kt
index f9709b9f..9bc1a58e 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20RawParquetTraceReader.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20RawParquetTraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +20,20 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.trace
+package org.opendc.experiments.sc20.trace
-import com.atlarge.opendc.compute.core.image.FlopsHistoryFragment
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.format.trace.TraceEntry
-import com.atlarge.opendc.format.trace.TraceReader
-import java.io.File
-import java.util.UUID
import mu.KotlinLogging
import org.apache.avro.generic.GenericData
import org.apache.hadoop.fs.Path
import org.apache.parquet.avro.AvroParquetReader
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.core.User
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.workload.SimTraceWorkload
+import java.io.File
+import java.util.UUID
private val logger = KotlinLogging.logger {}
@@ -45,16 +43,16 @@ private val logger = KotlinLogging.logger {}
* @param path The directory of the traces.
*/
@OptIn(ExperimentalStdlibApi::class)
-class Sc20RawParquetTraceReader(private val path: File) {
+public class Sc20RawParquetTraceReader(private val path: File) {
/**
* Read the fragments into memory.
*/
- private fun parseFragments(path: File): Map<String, List<FlopsHistoryFragment>> {
+ private fun parseFragments(path: File): Map<String, List<SimTraceWorkload.Fragment>> {
val reader = AvroParquetReader.builder<GenericData.Record>(Path(path.absolutePath, "trace.parquet"))
.disableCompatibility()
.build()
- val fragments = mutableMapOf<String, MutableList<FlopsHistoryFragment>>()
+ val fragments = mutableMapOf<String, MutableList<SimTraceWorkload.Fragment>>()
return try {
while (true) {
@@ -67,7 +65,7 @@ class Sc20RawParquetTraceReader(private val path: File) {
val cpuUsage = record["cpuUsage"] as Double
val flops = record["flops"] as Long
- val fragment = FlopsHistoryFragment(
+ val fragment = SimTraceWorkload.Fragment(
tick,
flops,
duration,
@@ -87,7 +85,7 @@ class Sc20RawParquetTraceReader(private val path: File) {
/**
* Read the metadata into a workload.
*/
- private fun parseMeta(path: File, fragments: Map<String, List<FlopsHistoryFragment>>): List<TraceEntryImpl> {
+ private fun parseMeta(path: File, fragments: Map<String, List<SimTraceWorkload.Fragment>>): List<TraceEntryImpl> {
val metaReader = AvroParquetReader.builder<GenericData.Record>(Path(path.absolutePath, "meta.parquet"))
.disableCompatibility()
.build()
@@ -113,19 +111,20 @@ class Sc20RawParquetTraceReader(private val path: File) {
val vmFragments = fragments.getValue(id).asSequence()
val totalLoad = vmFragments.sumByDouble { it.usage } * 5 * 60 // avg MHz * duration = MFLOPs
val vmWorkload = VmWorkload(
- uid, id,
+ uid,
+ id,
UnnamedUser,
- VmImage(
+ SimWorkloadImage(
uid,
id,
mapOf(
"submit-time" to submissionTime,
"end-time" to endTime,
- "total-load" to totalLoad
+ "total-load" to totalLoad,
+ "cores" to maxCores,
+ "required-memory" to requiredMemory
),
- vmFragments,
- maxCores,
- requiredMemory
+ SimTraceWorkload(vmFragments)
)
)
entries.add(TraceEntryImpl(submissionTime, vmWorkload))
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20StreamingParquetTraceReader.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20StreamingParquetTraceReader.kt
index 8b7b222f..edef276c 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20StreamingParquetTraceReader.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20StreamingParquetTraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,24 +20,8 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.trace
+package org.opendc.experiments.sc20.trace
-import com.atlarge.opendc.compute.core.image.FlopsHistoryFragment
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.core.workload.IMAGE_PERF_INTERFERENCE_MODEL
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.format.trace.TraceEntry
-import com.atlarge.opendc.format.trace.TraceReader
-import java.io.File
-import java.io.Serializable
-import java.util.SortedSet
-import java.util.TreeSet
-import java.util.UUID
-import java.util.concurrent.ArrayBlockingQueue
-import kotlin.concurrent.thread
-import kotlin.random.Random
import mu.KotlinLogging
import org.apache.avro.generic.GenericData
import org.apache.hadoop.fs.Path
@@ -49,6 +31,22 @@ import org.apache.parquet.filter2.predicate.FilterApi
import org.apache.parquet.filter2.predicate.Statistics
import org.apache.parquet.filter2.predicate.UserDefinedPredicate
import org.apache.parquet.io.api.Binary
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.core.User
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.interference.IMAGE_PERF_INTERFERENCE_MODEL
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
+import org.opendc.simulator.compute.workload.SimTraceWorkload
+import java.io.File
+import java.io.Serializable
+import java.util.SortedSet
+import java.util.TreeSet
+import java.util.UUID
+import java.util.concurrent.ArrayBlockingQueue
+import kotlin.concurrent.thread
+import kotlin.random.Random
private val logger = KotlinLogging.logger {}
@@ -59,7 +57,7 @@ private val logger = KotlinLogging.logger {}
* @param performanceInterferenceModel The performance model covering the workload in the VM trace.
*/
@OptIn(ExperimentalStdlibApi::class)
-class Sc20StreamingParquetTraceReader(
+public class Sc20StreamingParquetTraceReader(
traceFile: File,
performanceInterferenceModel: PerformanceInterferenceModel,
selectedVms: List<String>,
@@ -73,7 +71,7 @@ class Sc20StreamingParquetTraceReader(
/**
* The intermediate buffer to store the read records in.
*/
- private val queue = ArrayBlockingQueue<Pair<String, FlopsHistoryFragment>>(1024)
+ private val queue = ArrayBlockingQueue<Pair<String, SimTraceWorkload.Fragment>>(1024)
/**
* An optional filter for filtering the selected VMs
@@ -82,16 +80,19 @@ class Sc20StreamingParquetTraceReader(
if (selectedVms.isEmpty())
null
else
- FilterCompat.get(FilterApi.userDefined(FilterApi.binaryColumn("id"),
- SelectedVmFilter(
- TreeSet(selectedVms)
+ FilterCompat.get(
+ FilterApi.userDefined(
+ FilterApi.binaryColumn("id"),
+ SelectedVmFilter(
+ TreeSet(selectedVms)
+ )
)
- ))
+ )
/**
* A poisonous fragment.
*/
- private val poison = Pair("\u0000", FlopsHistoryFragment(0, 0, 0, 0.0, 0))
+ private val poison = Pair("\u0000", SimTraceWorkload.Fragment(0, 0, 0, 0.0, 0))
/**
* The thread to read the records in.
@@ -118,7 +119,7 @@ class Sc20StreamingParquetTraceReader(
val cpuUsage = record["cpuUsage"] as Double
val flops = record["flops"] as Long
- val fragment = FlopsHistoryFragment(
+ val fragment = SimTraceWorkload.Fragment(
tick,
flops,
duration,
@@ -138,12 +139,12 @@ class Sc20StreamingParquetTraceReader(
/**
* Fill the buffers with the VMs
*/
- private fun pull(buffers: Map<String, List<MutableList<FlopsHistoryFragment>>>) {
+ private fun pull(buffers: Map<String, List<MutableList<SimTraceWorkload.Fragment>>>) {
if (!hasNext) {
return
}
- val fragments = mutableListOf<Pair<String, FlopsHistoryFragment>>()
+ val fragments = mutableListOf<Pair<String, SimTraceWorkload.Fragment>>()
queue.drainTo(fragments)
for ((id, fragment) in fragments) {
@@ -166,7 +167,7 @@ class Sc20StreamingParquetTraceReader(
init {
val takenIds = mutableSetOf<UUID>()
val entries = mutableMapOf<String, GenericData.Record>()
- val buffers = mutableMapOf<String, MutableList<MutableList<FlopsHistoryFragment>>>()
+ val buffers = mutableMapOf<String, MutableList<MutableList<SimTraceWorkload.Fragment>>>()
val metaReader = AvroParquetReader.builder<GenericData.Record>(Path(traceFile.absolutePath, "meta.parquet"))
.disableCompatibility()
@@ -199,11 +200,11 @@ class Sc20StreamingParquetTraceReader(
logger.info("Processing VM $id")
- val internalBuffer = mutableListOf<FlopsHistoryFragment>()
- val externalBuffer = mutableListOf<FlopsHistoryFragment>()
+ val internalBuffer = mutableListOf<SimTraceWorkload.Fragment>()
+ val externalBuffer = mutableListOf<SimTraceWorkload.Fragment>()
buffers.getOrPut(id) { mutableListOf() }.add(externalBuffer)
- val fragments = sequence<FlopsHistoryFragment> {
- repeat@while (true) {
+ val fragments = sequence {
+ repeat@ while (true) {
if (externalBuffer.isEmpty()) {
if (hasNext) {
pull(buffers)
@@ -219,7 +220,7 @@ class Sc20StreamingParquetTraceReader(
for (fragment in internalBuffer) {
yield(fragment)
- if (fragment.tick >= endTime) {
+ if (fragment.time >= endTime) {
break@repeat
}
}
@@ -235,15 +236,18 @@ class Sc20StreamingParquetTraceReader(
Random(random.nextInt())
)
val vmWorkload = VmWorkload(
- uid, "VM Workload $id",
+ uid,
+ "VM Workload $id",
UnnamedUser,
- VmImage(
+ SimWorkloadImage(
uid,
id,
- mapOf(IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems),
- fragments,
- maxCores,
- requiredMemory
+ mapOf(
+ IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems,
+ "cores" to maxCores,
+ "required-memory" to requiredMemory
+ ),
+ SimTraceWorkload(fragments),
)
)
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20TraceConverter.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20TraceConverter.kt
index 56ddbb6d..bb2a75ee 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/Sc20TraceConverter.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/Sc20TraceConverter.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,8 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.trace
+package org.opendc.experiments.sc20.trace
-import com.atlarge.opendc.format.trace.sc20.Sc20VmPlacementReader
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.groups.OptionGroup
@@ -37,12 +34,6 @@ import com.github.ajalt.clikt.parameters.options.required
import com.github.ajalt.clikt.parameters.options.split
import com.github.ajalt.clikt.parameters.types.file
import com.github.ajalt.clikt.parameters.types.long
-import java.io.BufferedReader
-import java.io.File
-import java.io.FileReader
-import java.util.Random
-import kotlin.math.max
-import kotlin.math.min
import me.tongfei.progressbar.ProgressBar
import org.apache.avro.Schema
import org.apache.avro.SchemaBuilder
@@ -51,11 +42,18 @@ import org.apache.hadoop.fs.Path
import org.apache.parquet.avro.AvroParquetWriter
import org.apache.parquet.hadoop.ParquetWriter
import org.apache.parquet.hadoop.metadata.CompressionCodecName
+import org.opendc.format.trace.sc20.Sc20VmPlacementReader
+import java.io.BufferedReader
+import java.io.File
+import java.io.FileReader
+import java.util.Random
+import kotlin.math.max
+import kotlin.math.min
/**
* Represents the command for converting traces
*/
-class TraceConverterCli : CliktCommand(name = "trace-converter") {
+public class TraceConverterCli : CliktCommand(name = "trace-converter") {
/**
* The directory where the trace should be stored.
*/
@@ -72,7 +70,7 @@ class TraceConverterCli : CliktCommand(name = "trace-converter") {
/**
* The input type of the trace.
*/
- val type by option("-t", "--type", help = "input type of trace").groupChoice(
+ private val type by option("-t", "--type", help = "input type of trace").groupChoice(
"solvinity" to SolvinityConversion(),
"bitbrains" to BitbrainsConversion(),
"azure" to AzureConversion()
@@ -81,7 +79,7 @@ class TraceConverterCli : CliktCommand(name = "trace-converter") {
override fun run() {
val metaSchema = SchemaBuilder
.record("meta")
- .namespace("com.atlarge.opendc.format.sc20")
+ .namespace("org.opendc.format.sc20")
.fields()
.name("id").type().stringType().noDefault()
.name("submissionTime").type().longType().noDefault()
@@ -91,7 +89,7 @@ class TraceConverterCli : CliktCommand(name = "trace-converter") {
.endRecord()
val schema = SchemaBuilder
.record("trace")
- .namespace("com.atlarge.opendc.format.sc20")
+ .namespace("org.opendc.format.sc20")
.fields()
.name("id").type().stringType().noDefault()
.name("time").type().longType().noDefault()
@@ -151,22 +149,22 @@ class TraceConverterCli : CliktCommand(name = "trace-converter") {
/**
* The supported trace conversions.
*/
-sealed class TraceConversion(name: String) : OptionGroup(name) {
+public sealed class TraceConversion(name: String) : OptionGroup(name) {
/**
* Read the fragments of the trace.
*/
- abstract fun read(
+ public abstract fun read(
traceDirectory: File,
metaSchema: Schema,
metaWriter: ParquetWriter<GenericData.Record>
): MutableList<Fragment>
}
-class SolvinityConversion : TraceConversion("Solvinity") {
- val clusters by option()
+public class SolvinityConversion : TraceConversion("Solvinity") {
+ private val clusters by option()
.split(",")
- val vmPlacements by option("--vm-placements", help = "file containing the VM placements")
+ private val vmPlacements by option("--vm-placements", help = "file containing the VM placements")
.file(canBeDir = false)
.convert { it.inputStream().buffered().use { Sc20VmPlacementReader(it).construct() } }
.required()
@@ -189,11 +187,11 @@ class SolvinityConversion : TraceConversion("Solvinity") {
.filterNot { it.isDirectory }
.filter { it.extension == "csv" || it.extension == "txt" }
.toList()
- .forEach { vmFile ->
+ .forEach file@{ vmFile ->
BufferedReader(FileReader(vmFile)).use { reader ->
reader.lineSequence()
.chunked(128)
- .forEachIndexed { idx, lines ->
+ .forEach { lines ->
for (line in lines) {
// Ignore comments in the trace
if (line.startsWith("#") || line.isBlank()) {
@@ -214,7 +212,7 @@ class SolvinityConversion : TraceConversion("Solvinity") {
if (timestamp < minTimestamp) {
minTimestamp = timestamp
}
- return@forEach
+ return@file
}
}
}
@@ -231,13 +229,13 @@ class SolvinityConversion : TraceConversion("Solvinity") {
.filterNot { it.isDirectory }
.filter { it.extension == "csv" || it.extension == "txt" }
.toList()
- .forEachIndexed { idx, vmFile ->
+ .forEach { vmFile ->
println(vmFile)
var vmId = ""
var maxCores = -1
var requiredMemory = -1L
- var cores = -1
+ var cores: Int
var minTime = Long.MAX_VALUE
val flopsFragments = sequence {
@@ -263,7 +261,8 @@ class SolvinityConversion : TraceConversion("Solvinity") {
continue
}
- val timestamp = (values[timestampCol].trim().toLong() - 5 * 60) * 1000L - minTimestamp
+ val timestamp =
+ (values[timestampCol].trim().toLong() - 5 * 60) * 1000L - minTimestamp
if (begin > timestamp || timestamp > end) {
continue
}
@@ -336,7 +335,7 @@ class SolvinityConversion : TraceConversion("Solvinity") {
/**
* Conversion of the Bitbrains public trace.
*/
-class BitbrainsConversion : TraceConversion("Bitbrains") {
+public class BitbrainsConversion : TraceConversion("Bitbrains") {
override fun read(
traceDirectory: File,
metaSchema: Schema,
@@ -354,13 +353,13 @@ class BitbrainsConversion : TraceConversion("Bitbrains") {
.filterNot { it.isDirectory }
.filter { it.extension == "csv" || it.extension == "txt" }
.toList()
- .forEachIndexed { idx, vmFile ->
+ .forEach { vmFile ->
println(vmFile)
var vmId = ""
var maxCores = -1
var requiredMemory = -1L
- var cores = -1
+ var cores: Int
var minTime = Long.MAX_VALUE
val flopsFragments = sequence {
@@ -384,7 +383,8 @@ class BitbrainsConversion : TraceConversion("Bitbrains") {
val timestamp = (values[timestampCol].trim().toLong() - 5 * 60) * 1000L
cores = values[coreCol].trim().toInt()
- requiredMemory = max(requiredMemory, values[provisionedMemoryCol].trim().toDouble().toLong())
+ requiredMemory =
+ max(requiredMemory, values[provisionedMemoryCol].trim().toDouble().toLong())
maxCores = max(maxCores, cores)
minTime = min(minTime, timestamp)
val cpuUsage = values[cpuUsageCol].trim().toDouble() // MHz
@@ -447,8 +447,8 @@ class BitbrainsConversion : TraceConversion("Bitbrains") {
/**
* Conversion of the Azure public VM trace.
*/
-class AzureConversion : TraceConversion("Azure") {
- val seed by option(help = "seed for trace sampling")
+public class AzureConversion : TraceConversion("Azure") {
+ private val seed by option(help = "seed for trace sampling")
.long()
.default(0)
@@ -604,18 +604,18 @@ class AzureConversion : TraceConversion("Azure") {
}
}
-data class Fragment(
- val id: String,
- val tick: Long,
- val flops: Long,
- val duration: Long,
- val usage: Double,
- val cores: Int
+public data class Fragment(
+ public val id: String,
+ public val tick: Long,
+ public val flops: Long,
+ public val duration: Long,
+ public val usage: Double,
+ public val cores: Int
)
-class VmInfo(val cores: Int, val requiredMemory: Long, var minTime: Long, var maxTime: Long)
+public class VmInfo(public val cores: Int, public val requiredMemory: Long, public var minTime: Long, public var maxTime: Long)
/**
* A script to convert a trace in text format into a Parquet trace.
*/
-fun main(args: Array<String>) = TraceConverterCli().main(args)
+public fun main(args: Array<String>): Unit = TraceConverterCli().main(args)
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/WorkloadSampler.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/WorkloadSampler.kt
index a46bb3e6..a8b83aef 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/trace/WorkloadSampler.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/kotlin/org/opendc/experiments/sc20/trace/WorkloadSampler.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,24 +20,24 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20.trace
+package org.opendc.experiments.sc20.trace
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.experiments.sc20.experiment.model.CompositeWorkload
-import com.atlarge.opendc.experiments.sc20.experiment.model.SamplingStrategy
-import com.atlarge.opendc.experiments.sc20.experiment.model.Workload
-import com.atlarge.opendc.format.trace.TraceEntry
+import mu.KotlinLogging
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.experiments.sc20.experiment.model.CompositeWorkload
+import org.opendc.experiments.sc20.experiment.model.SamplingStrategy
+import org.opendc.experiments.sc20.experiment.model.Workload
+import org.opendc.format.trace.TraceEntry
import java.util.*
import kotlin.random.Random
-import mu.KotlinLogging
private val logger = KotlinLogging.logger {}
/**
* Sample the workload for the specified [run].
*/
-fun sampleWorkload(
+public fun sampleWorkload(
trace: List<TraceEntry<VmWorkload>>,
workload: Workload,
subWorkload: Workload,
@@ -59,7 +57,7 @@ fun sampleWorkload(
/**
* Sample a regular (non-HPC) workload.
*/
-fun sampleRegularWorkload(
+public fun sampleRegularWorkload(
trace: List<TraceEntry<VmWorkload>>,
workload: Workload,
subWorkload: Workload,
@@ -94,7 +92,7 @@ fun sampleRegularWorkload(
/**
* Sample a HPC workload.
*/
-fun sampleHpcWorkload(
+public fun sampleHpcWorkload(
trace: List<TraceEntry<VmWorkload>>,
workload: Workload,
seed: Int,
@@ -145,7 +143,6 @@ fun sampleHpcWorkload(
if (sampleOnLoad) {
var currentLoad = 0.0
- var i = 0
for (entry in hpcSequence) {
val entryLoad = entry.workload.image.tags.getValue("total-load") as Double
if ((currentLoad + entryLoad) / totalLoad > fraction) {
@@ -199,16 +196,15 @@ fun sampleHpcWorkload(
*/
private fun sample(entry: TraceEntry<VmWorkload>, i: Int): TraceEntry<VmWorkload> {
val id = UUID.nameUUIDFromBytes("${entry.workload.image.uid}-$i".toByteArray())
- val image = VmImage(
+ val image = SimWorkloadImage(
id,
entry.workload.image.name,
entry.workload.image.tags,
- entry.workload.image.flopsHistory,
- entry.workload.image.maxCores,
- entry.workload.image.requiredMemory
+ (entry.workload.image as SimWorkloadImage).workload
)
val vmWorkload = entry.workload.copy(uid = id, image = image, name = entry.workload.name)
return VmTraceEntry(vmWorkload, entry.submissionTime)
}
-private class VmTraceEntry(override val workload: VmWorkload, override val submissionTime: Long) : TraceEntry<VmWorkload>
+private class VmTraceEntry(override val workload: VmWorkload, override val submissionTime: Long) :
+ TraceEntry<VmWorkload>
diff --git a/simulator/opendc/opendc-experiments-sc20/src/main/resources/log4j2.xml b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/resources/log4j2.xml
index 6906bfc3..8029092e 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/main/resources/log4j2.xml
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/main/resources/log4j2.xml
@@ -26,20 +26,17 @@
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} [%highlight{%-5level}] %logger{36} - %msg%n" disableAnsi="false" />
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} [%highlight{%-5level}] %logger{36} - %msg%n" disableAnsi="false"/>
</Console>
</Appenders>
<Loggers>
- <Logger name="com.atlarge.odcsim" level="info" additivity="false">
+ <Logger name="org.opendc" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
- <Logger name="com.atlarge.opendc" level="warn" additivity="false">
+ <Logger name="org.opendc.experiments.sc20" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
- <Logger name="com.atlarge.opendc.experiments.sc20" level="info" additivity="false">
- <AppenderRef ref="Console"/>
- </Logger>
- <Logger name="com.atlarge.opendc.experiments.sc20.trace" level="debug" additivity="false">
+ <Logger name="org.opendc.experiments.sc20.trace" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.apache.hadoop" level="warn" additivity="false">
diff --git a/simulator/opendc/opendc-experiments-sc20/src/test/kotlin/com/atlarge/opendc/experiments/sc20/Sc20IntegrationTest.kt b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/kotlin/org/opendc/experiments/sc20/Sc20IntegrationTest.kt
index a79e9a5a..9c44edfc 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/test/kotlin/com/atlarge/opendc/experiments/sc20/Sc20IntegrationTest.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/kotlin/org/opendc/experiments/sc20/Sc20IntegrationTest.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,52 +20,51 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.experiments.sc20
-
-import com.atlarge.odcsim.Domain
-import com.atlarge.odcsim.SimulationEngine
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-import com.atlarge.opendc.compute.virt.service.allocation.AvailableCoreMemoryAllocationPolicy
-import com.atlarge.opendc.experiments.sc20.experiment.attachMonitor
-import com.atlarge.opendc.experiments.sc20.experiment.createFailureDomain
-import com.atlarge.opendc.experiments.sc20.experiment.createProvisioner
-import com.atlarge.opendc.experiments.sc20.experiment.model.Workload
-import com.atlarge.opendc.experiments.sc20.experiment.monitor.ExperimentMonitor
-import com.atlarge.opendc.experiments.sc20.experiment.processTrace
-import com.atlarge.opendc.experiments.sc20.trace.Sc20ParquetTraceReader
-import com.atlarge.opendc.experiments.sc20.trace.Sc20RawParquetTraceReader
-import com.atlarge.opendc.format.environment.EnvironmentReader
-import com.atlarge.opendc.format.environment.sc20.Sc20ClusterEnvironmentReader
-import com.atlarge.opendc.format.trace.TraceReader
-import java.io.File
-import java.util.ServiceLoader
+package org.opendc.experiments.sc20
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestCoroutineScope
import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.Assertions.assertAll
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimVirtProvisioningService
+import org.opendc.compute.simulator.allocation.AvailableCoreMemoryAllocationPolicy
+import org.opendc.experiments.sc20.experiment.attachMonitor
+import org.opendc.experiments.sc20.experiment.createFailureDomain
+import org.opendc.experiments.sc20.experiment.createProvisioner
+import org.opendc.experiments.sc20.experiment.model.Workload
+import org.opendc.experiments.sc20.experiment.monitor.ExperimentMonitor
+import org.opendc.experiments.sc20.experiment.processTrace
+import org.opendc.experiments.sc20.trace.Sc20ParquetTraceReader
+import org.opendc.experiments.sc20.trace.Sc20RawParquetTraceReader
+import org.opendc.format.environment.EnvironmentReader
+import org.opendc.format.environment.sc20.Sc20ClusterEnvironmentReader
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import java.io.File
+import java.time.Clock
/**
* An integration test suite for the SC20 experiments.
*/
+@OptIn(ExperimentalCoroutinesApi::class)
class Sc20IntegrationTest {
/**
- * The simulation engine to use.
+ * The [TestCoroutineScope] to use.
*/
- private lateinit var simulationEngine: SimulationEngine
+ private lateinit var testScope: TestCoroutineScope
/**
- * The root simulation domain to run in.
+ * The simulation clock to use.
*/
- private lateinit var root: Domain
+ private lateinit var clock: Clock
/**
* The monitor used to keep track of the metrics.
@@ -79,9 +76,9 @@ class Sc20IntegrationTest {
*/
@BeforeEach
fun setUp() {
- val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
- simulationEngine = provider("test")
- root = simulationEngine.newDomain("root")
+ testScope = TestCoroutineScope()
+ clock = DelayControllerClockAdapter(testScope)
+
monitor = TestExperimentReporter()
}
@@ -89,9 +86,7 @@ class Sc20IntegrationTest {
* Tear down the experimental environment.
*/
@AfterEach
- fun tearDown() = runBlocking {
- simulationEngine.terminate()
- }
+ fun tearDown() = testScope.cleanupTestCoroutines()
@Test
fun smoke() {
@@ -101,11 +96,12 @@ class Sc20IntegrationTest {
val allocationPolicy = AvailableCoreMemoryAllocationPolicy()
val traceReader = createTestTraceReader()
val environmentReader = createTestEnvironmentReader()
- lateinit var scheduler: SimpleVirtProvisioningService
+ lateinit var scheduler: SimVirtProvisioningService
- root.launch {
+ testScope.launch {
val res = createProvisioner(
- root,
+ this,
+ clock,
environmentReader,
allocationPolicy
)
@@ -115,6 +111,8 @@ class Sc20IntegrationTest {
val failureDomain = if (failures) {
println("ENABLING failures")
createFailureDomain(
+ this,
+ clock,
seed,
24.0 * 7,
bareMetalProvisioner,
@@ -124,8 +122,10 @@ class Sc20IntegrationTest {
null
}
- attachMonitor(scheduler, monitor)
+ attachMonitor(this, clock, scheduler, monitor)
processTrace(
+ this,
+ clock,
traceReader,
scheduler,
chan,
@@ -142,12 +142,14 @@ class Sc20IntegrationTest {
runSimulation()
// Note that these values have been verified beforehand
- assertEquals(50, scheduler.submittedVms, "The trace contains 50 VMs")
- assertEquals(50, scheduler.finishedVms, "All VMs should finish after a run")
- assertEquals(207379117949, monitor.totalRequestedBurst)
- assertEquals(203388071813, monitor.totalGrantedBurst)
- assertEquals(3991046136, monitor.totalOvercommissionedBurst)
- assertEquals(0, monitor.totalInterferedBurst)
+ assertAll(
+ { assertEquals(50, scheduler.submittedVms, "The trace contains 50 VMs") },
+ { assertEquals(50, scheduler.finishedVms, "All VMs should finish after a run") },
+ { assertEquals(207379117949, monitor.totalRequestedBurst) },
+ { assertEquals(203388071813, monitor.totalGrantedBurst) },
+ { assertEquals(3991046136, monitor.totalOvercommissionedBurst) },
+ { assertEquals(0, monitor.totalInterferedBurst) }
+ )
}
@Test
@@ -157,18 +159,21 @@ class Sc20IntegrationTest {
val allocationPolicy = AvailableCoreMemoryAllocationPolicy()
val traceReader = createTestTraceReader(0.5, seed)
val environmentReader = createTestEnvironmentReader("single")
- lateinit var scheduler: SimpleVirtProvisioningService
+ lateinit var scheduler: SimVirtProvisioningService
- root.launch {
+ testScope.launch {
val res = createProvisioner(
- root,
+ this,
+ clock,
environmentReader,
allocationPolicy
)
scheduler = res.second
- attachMonitor(scheduler, monitor)
+ attachMonitor(this, clock, scheduler, monitor)
processTrace(
+ this,
+ clock,
traceReader,
scheduler,
chan,
@@ -195,9 +200,7 @@ class Sc20IntegrationTest {
/**
* Run the simulation.
*/
- private fun runSimulation() = runBlocking {
- simulationEngine.run()
- }
+ private fun runSimulation() = testScope.advanceUntilIdle()
/**
* Obtain the trace reader for the test.
diff --git a/simulator/opendc/opendc-experiments-sc20/src/test/resources/env/single.txt b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/env/single.txt
index 53b3c2d7..53b3c2d7 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/test/resources/env/single.txt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/env/single.txt
diff --git a/simulator/opendc/opendc-experiments-sc20/src/test/resources/env/topology.txt b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/env/topology.txt
index 6b347bff..6b347bff 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/test/resources/env/topology.txt
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/env/topology.txt
diff --git a/simulator/opendc/opendc-experiments-sc20/src/test/resources/trace/meta.parquet b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/trace/meta.parquet
index ce7a812c..ce7a812c 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/test/resources/trace/meta.parquet
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/trace/meta.parquet
Binary files differ
diff --git a/simulator/opendc/opendc-experiments-sc20/src/test/resources/trace/trace.parquet b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/trace/trace.parquet
index 1d7ce882..1d7ce882 100644
--- a/simulator/opendc/opendc-experiments-sc20/src/test/resources/trace/trace.parquet
+++ b/simulator/opendc-experiments/opendc-experiments-sc20/src/test/resources/trace/trace.parquet
Binary files differ
diff --git a/simulator/opendc/opendc-format/build.gradle.kts b/simulator/opendc-format/build.gradle.kts
index 4414b638..30aafc90 100644
--- a/simulator/opendc/opendc-format/build.gradle.kts
+++ b/simulator/opendc-format/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2019 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,13 +28,22 @@ plugins {
}
dependencies {
- api(project(":opendc:opendc-core"))
- api(project(":opendc:opendc-compute"))
- api(project(":opendc:opendc-workflows"))
- api("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8")
- implementation(kotlin("stdlib"))
+ api(project(":opendc-core"))
+ api(project(":opendc-compute:opendc-compute-core"))
+ api(project(":opendc-workflows"))
+ implementation(project(":opendc-simulator:opendc-simulator-compute"))
+ implementation(project(":opendc-compute:opendc-compute-simulator"))
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8") {
+ exclude("org.jetbrains.kotlin", module = "kotlin-reflect")
+ }
implementation(kotlin("reflect"))
+ implementation("org.apache.parquet:parquet-avro:1.11.0")
+ implementation("org.apache.hadoop:hadoop-client:3.2.1") {
+ exclude(group = "org.slf4j", module = "slf4j-log4j12")
+ exclude(group = "log4j")
+ }
+
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
testImplementation("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}")
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/EnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt
index 1c3f70e6..1f73bb61 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/EnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,19 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.environment
+package org.opendc.format.environment
-import com.atlarge.odcsim.Domain
-import com.atlarge.opendc.core.Environment
+import kotlinx.coroutines.CoroutineScope
+import org.opendc.core.Environment
import java.io.Closeable
+import java.time.Clock
/**
* An interface for reading descriptions of topology environments into memory as [Environment].
*/
-interface EnvironmentReader : Closeable {
+public interface EnvironmentReader : Closeable {
/**
- * Construct an [Environment] in the specified domain.
+ * Construct an [Environment] in the specified [CoroutineScope].
*/
- suspend fun construct(dom: Domain): Environment
+ public suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment
}
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc18/Model.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Model.kt
index f3e70982..c313467f 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc18/Model.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Model.kt
@@ -1,4 +1,26 @@
-package com.atlarge.opendc.format.environment.sc18
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.format.environment.sc18
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc18/Sc18EnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt
index a9aa3337..2e3e4a73 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc18/Sc18EnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,25 +20,27 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.environment.sc18
+package org.opendc.format.environment.sc18
-import com.atlarge.odcsim.Domain
-import com.atlarge.opendc.compute.core.MemoryUnit
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.compute.metal.service.SimpleProvisioningService
-import com.atlarge.opendc.core.Environment
-import com.atlarge.opendc.core.Platform
-import com.atlarge.opendc.core.Zone
-import com.atlarge.opendc.core.services.ServiceRegistry
-import com.atlarge.opendc.format.environment.EnvironmentReader
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
+import kotlinx.coroutines.CoroutineScope
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.compute.core.metal.service.SimpleProvisioningService
+import org.opendc.compute.simulator.SimBareMetalDriver
+import org.opendc.core.Environment
+import org.opendc.core.Platform
+import org.opendc.core.Zone
+import org.opendc.core.services.ServiceRegistry
+import org.opendc.format.environment.EnvironmentReader
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
import java.io.InputStream
-import java.util.UUID
+import java.time.Clock
+import java.util.*
/**
* A parser for the JSON experiment setup files used for the SC18 paper: "A Reference Architecture for Topology
@@ -49,15 +49,13 @@ import java.util.UUID
* @param input The input stream to read from.
* @param mapper The Jackson object mapper to use.
*/
-class Sc18EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) : EnvironmentReader {
+public class Sc18EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) : EnvironmentReader {
/**
* The environment that was read from the file.
*/
private val setup: Setup = mapper.readValue(input)
- override suspend fun construct(dom: Domain): Environment {
- val provisioningDomain = dom.newDomain("provisioner")
-
+ override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
var counter = 0
val nodes = setup.rooms.flatMap { room ->
room.objects.flatMap { roomObject ->
@@ -77,13 +75,13 @@ class Sc18EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonOb
else -> throw IllegalArgumentException("The cpu id $id is not recognized")
}
}
- SimpleBareMetalDriver(
- dom.newDomain("node-$counter"),
+ SimBareMetalDriver(
+ coroutineScope,
+ clock,
UUID.randomUUID(),
"node-${counter++}",
emptyMap(),
- cores,
- listOf(MemoryUnit("", "", 2300.0, 16000))
+ SimMachineModel(cores, listOf(MemoryUnit("", "", 2300.0, 16000)))
)
}
}
@@ -91,14 +89,16 @@ class Sc18EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonOb
}
}
- val provisioningService = SimpleProvisioningService(provisioningDomain)
+ val provisioningService = SimpleProvisioningService()
for (node in nodes) {
provisioningService.create(node)
}
val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
val platform = Platform(
- UUID.randomUUID(), "sc18-platform", listOf(
+ UUID.randomUUID(),
+ "sc18-platform",
+ listOf(
Zone(UUID.randomUUID(), "zone", serviceRegistry)
)
)
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Model.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Model.kt
index 0a8f1c14..58af8453 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Model.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Model.kt
@@ -1,4 +1,26 @@
-package com.atlarge.opendc.format.environment.sc20
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.format.environment.sc20
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt
index e34ee2dc..b4c71c4e 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,41 +20,42 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.environment.sc20
-
-import com.atlarge.odcsim.Domain
-import com.atlarge.opendc.compute.core.MemoryUnit
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.metal.NODE_CLUSTER
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import com.atlarge.opendc.compute.metal.power.LinearLoadPowerModel
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.compute.metal.service.SimpleProvisioningService
-import com.atlarge.opendc.core.Environment
-import com.atlarge.opendc.core.Platform
-import com.atlarge.opendc.core.Zone
-import com.atlarge.opendc.core.services.ServiceRegistry
-import com.atlarge.opendc.format.environment.EnvironmentReader
+package org.opendc.format.environment.sc20
+
+import kotlinx.coroutines.CoroutineScope
+import org.opendc.compute.core.metal.NODE_CLUSTER
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.compute.core.metal.service.SimpleProvisioningService
+import org.opendc.compute.simulator.SimBareMetalDriver
+import org.opendc.compute.simulator.power.LinearLoadPowerModel
+import org.opendc.core.Environment
+import org.opendc.core.Platform
+import org.opendc.core.Zone
+import org.opendc.core.services.ServiceRegistry
+import org.opendc.format.environment.EnvironmentReader
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
-import java.util.Random
-import java.util.UUID
+import java.time.Clock
+import java.util.*
/**
* A [EnvironmentReader] for the internal environment format.
*
* @param environmentFile The file describing the physical cluster.
*/
-class Sc20ClusterEnvironmentReader(
+public class Sc20ClusterEnvironmentReader(
private val input: InputStream
) : EnvironmentReader {
- constructor(file: File) : this(FileInputStream(file))
+ public constructor(file: File) : this(FileInputStream(file))
@Suppress("BlockingMethodInNonBlockingContext")
- override suspend fun construct(dom: Domain): Environment {
+ override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
var clusterIdCol = 0
var speedCol = 0
var numberOfHostsCol = 0
@@ -70,7 +69,7 @@ class Sc20ClusterEnvironmentReader(
var memoryPerHost: Long
var coresPerHost: Int
- val nodes = mutableListOf<SimpleBareMetalDriver>()
+ val nodes = mutableListOf<SimBareMetalDriver>()
val random = Random(0)
input.bufferedReader().use { reader ->
@@ -104,18 +103,21 @@ class Sc20ClusterEnvironmentReader(
repeat(numberOfHosts) {
nodes.add(
- SimpleBareMetalDriver(
- dom.newDomain("node-$clusterId-$it"),
+ SimBareMetalDriver(
+ coroutineScope,
+ clock,
UUID(random.nextLong(), random.nextLong()),
"node-$clusterId-$it",
mapOf(NODE_CLUSTER to clusterId),
- List(coresPerHost) { coreId ->
- ProcessingUnit(unknownProcessingNode, coreId, speed)
- },
+ SimMachineModel(
+ List(coresPerHost) { coreId ->
+ ProcessingUnit(unknownProcessingNode, coreId, speed)
+ },
+ listOf(unknownMemoryUnit)
+ ),
// For now we assume a simple linear load model with an idle draw of ~200W and a maximum
// power draw of 350W.
// Source: https://stackoverflow.com/questions/6128960
- listOf(unknownMemoryUnit),
LinearLoadPowerModel(200.0, 350.0)
)
)
@@ -123,7 +125,7 @@ class Sc20ClusterEnvironmentReader(
}
}
- val provisioningService = SimpleProvisioningService(dom.newDomain("provisioner"))
+ val provisioningService = SimpleProvisioningService()
for (node in nodes) {
provisioningService.create(node)
}
@@ -131,7 +133,9 @@ class Sc20ClusterEnvironmentReader(
val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
val platform = Platform(
- UUID.randomUUID(), "sc20-platform", listOf(
+ UUID.randomUUID(),
+ "sc20-platform",
+ listOf(
Zone(UUID.randomUUID(), "zone", serviceRegistry)
)
)
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Sc20EnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt
index 4b5d6fb7..94237cb9 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/environment/sc20/Sc20EnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,26 +20,28 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.environment.sc20
+package org.opendc.format.environment.sc20
-import com.atlarge.odcsim.Domain
-import com.atlarge.opendc.compute.core.MemoryUnit
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import com.atlarge.opendc.compute.metal.power.LinearLoadPowerModel
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.compute.metal.service.SimpleProvisioningService
-import com.atlarge.opendc.core.Environment
-import com.atlarge.opendc.core.Platform
-import com.atlarge.opendc.core.Zone
-import com.atlarge.opendc.core.services.ServiceRegistry
-import com.atlarge.opendc.format.environment.EnvironmentReader
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
+import kotlinx.coroutines.CoroutineScope
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.compute.core.metal.service.SimpleProvisioningService
+import org.opendc.compute.simulator.SimBareMetalDriver
+import org.opendc.compute.simulator.power.LinearLoadPowerModel
+import org.opendc.core.Environment
+import org.opendc.core.Platform
+import org.opendc.core.Zone
+import org.opendc.core.services.ServiceRegistry
+import org.opendc.format.environment.EnvironmentReader
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
import java.io.InputStream
-import java.util.UUID
+import java.time.Clock
+import java.util.*
/**
* A parser for the JSON experiment setup files used for the SC20 paper.
@@ -49,13 +49,13 @@ import java.util.UUID
* @param input The input stream to read from.
* @param mapper The Jackson object mapper to use.
*/
-class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) : EnvironmentReader {
+public class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) : EnvironmentReader {
/**
* The environment that was read from the file.
*/
private val setup: Setup = mapper.readValue(input)
- override suspend fun construct(dom: Domain): Environment {
+ override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
var counter = 0
val nodes = setup.rooms.flatMap { room ->
room.objects.flatMap { roomObject ->
@@ -81,16 +81,16 @@ class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonOb
else -> throw IllegalArgumentException("The cpu id $id is not recognized")
}
}
- SimpleBareMetalDriver(
- dom.newDomain("node-$counter"),
+ SimBareMetalDriver(
+ coroutineScope,
+ clock,
UUID.randomUUID(),
"node-${counter++}",
emptyMap(),
- cores,
+ SimMachineModel(cores, memories),
// For now we assume a simple linear load model with an idle draw of ~200W and a maximum
// power draw of 350W.
// Source: https://stackoverflow.com/questions/6128960
- memories,
LinearLoadPowerModel(200.0, 350.0)
)
}
@@ -99,7 +99,7 @@ class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonOb
}
}
- val provisioningService = SimpleProvisioningService(dom.newDomain("provisioner"))
+ val provisioningService = SimpleProvisioningService()
for (node in nodes) {
provisioningService.create(node)
}
@@ -107,7 +107,9 @@ class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = jacksonOb
val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
val platform = Platform(
- UUID.randomUUID(), "sc20-platform", listOf(
+ UUID.randomUUID(),
+ "sc20-platform",
+ listOf(
Zone(UUID.randomUUID(), "zone", serviceRegistry)
)
)
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/PerformanceInterferenceModelReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/PerformanceInterferenceModelReader.kt
index 407bc0b4..f30e64cf 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/PerformanceInterferenceModelReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/PerformanceInterferenceModelReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace
+package org.opendc.format.trace
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
import java.io.Closeable
import kotlin.random.Random
/**
* An interface for reading descriptions of performance interference models into memory.
*/
-interface PerformanceInterferenceModelReader : Closeable {
+public interface PerformanceInterferenceModelReader : Closeable {
/**
* Construct a [PerformanceInterferenceModel].
*/
- fun construct(random: Random): Map<String, PerformanceInterferenceModel>
+ public fun construct(random: Random): Map<String, PerformanceInterferenceModel>
}
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceEntry.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceEntry.kt
index d4ad33f7..ec547e84 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceEntry.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceEntry.kt
@@ -22,33 +22,33 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace
+package org.opendc.format.trace
-import com.atlarge.opendc.core.workload.Workload
+import org.opendc.core.workload.Workload
/**
* An entry in a workload trace.
*
* @param T The shape of the workload in this entry.
*/
-interface TraceEntry<T : Workload> {
+public interface TraceEntry<T : Workload> {
/**
* The time of submission of the workload.
*/
- val submissionTime: Long
+ public val submissionTime: Long
/**
* The workload in this trace entry.
*/
- val workload: T
+ public val workload: T
/**
* Extract the submission time from this entry.
*/
- operator fun component1() = submissionTime
+ public operator fun component1(): Long = submissionTime
/**
* Extract the workload from this entry.
*/
- operator fun component2() = workload
+ public operator fun component2(): T = workload
}
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceReader.kt
index 6d29cdb4..a0beec3e 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace
+package org.opendc.format.trace
-import com.atlarge.opendc.core.workload.Workload
+import org.opendc.core.workload.Workload
import java.io.Closeable
/**
@@ -34,4 +32,4 @@ import java.io.Closeable
*
* @param T The shape of the workloads supported by this reader.
*/
-interface TraceReader<T : Workload> : Iterator<TraceEntry<T>>, Closeable
+public interface TraceReader<T : Workload> : Iterator<TraceEntry<T>>, Closeable
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceWriter.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceWriter.kt
index 94ee6f31..54fb6214 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/TraceWriter.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/TraceWriter.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace
+package org.opendc.format.trace
-import com.atlarge.opendc.core.workload.Workload
+import org.opendc.core.workload.Workload
import java.io.Closeable
/**
@@ -32,7 +32,7 @@ import java.io.Closeable
*
* @param T The type of [Workload] supported by this writer.
*/
-interface TraceWriter<T : Workload> : Closeable {
+public interface TraceWriter<T : Workload> : Closeable {
/**
* Write an entry to the trace.
*
@@ -41,5 +41,5 @@ interface TraceWriter<T : Workload> : Closeable {
* @param submissionTime The time of submission of the workload.
* @param workload The workload to write to the trace.
*/
- fun write(submissionTime: Long, workload: T)
+ public fun write(submissionTime: Long, workload: T)
}
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/VmPlacementReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/VmPlacementReader.kt
index 7caebb76..6861affe 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/VmPlacementReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/VmPlacementReader.kt
@@ -22,16 +22,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace
+package org.opendc.format.trace
import java.io.Closeable
/**
* An interface for reading VM placement data into memory.
*/
-interface VmPlacementReader : Closeable {
+public interface VmPlacementReader : Closeable {
/**
* Construct a map of VMs to clusters.
*/
- fun construct(): Map<String, String>
+ public fun construct(): Map<String, String>
}
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/bitbrains/BitbrainsTraceReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/bitbrains/BitbrainsTraceReader.kt
index 1cabc8bc..9353ef28 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/bitbrains/BitbrainsTraceReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/bitbrains/BitbrainsTraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +20,20 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace.bitbrains
+package org.opendc.format.trace.bitbrains
-import com.atlarge.opendc.compute.core.image.FlopsHistoryFragment
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.core.workload.IMAGE_PERF_INTERFERENCE_MODEL
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.format.trace.TraceEntry
-import com.atlarge.opendc.format.trace.TraceReader
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.core.User
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.interference.IMAGE_PERF_INTERFERENCE_MODEL
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
+import org.opendc.simulator.compute.workload.SimTraceWorkload
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
-import java.util.UUID
+import java.util.*
/**
* A [TraceReader] for the public VM workload trace format.
@@ -43,7 +41,7 @@ import java.util.UUID
* @param traceDirectory The directory of the traces.
* @param performanceInterferenceModel The performance model covering the workload in the VM trace.
*/
-class BitbrainsTraceReader(
+public class BitbrainsTraceReader(
traceDirectory: File,
performanceInterferenceModel: PerformanceInterferenceModel
) : TraceReader<VmWorkload> {
@@ -68,7 +66,7 @@ class BitbrainsTraceReader(
.filterNot { it.isDirectory }
.forEach { vmFile ->
println(vmFile)
- val flopsHistory = mutableListOf<FlopsHistoryFragment>()
+ val flopsHistory = mutableListOf<SimTraceWorkload.Fragment>()
var vmId = -1L
var cores = -1
var requiredMemory = -1L
@@ -101,15 +99,23 @@ class BitbrainsTraceReader(
val flops: Long = (cpuUsage * 5 * 60 * cores).toLong()
if (flopsHistory.isEmpty()) {
- flopsHistory.add(FlopsHistoryFragment(timestamp, flops, traceInterval, cpuUsage, cores))
+ flopsHistory.add(SimTraceWorkload.Fragment(timestamp, flops, traceInterval, cpuUsage, cores))
} else {
if (flopsHistory.last().flops != flops) {
- flopsHistory.add(FlopsHistoryFragment(timestamp, flops, traceInterval, cpuUsage, cores))
+ flopsHistory.add(
+ SimTraceWorkload.Fragment(
+ timestamp,
+ flops,
+ traceInterval,
+ cpuUsage,
+ cores
+ )
+ )
} else {
val oldFragment = flopsHistory.removeAt(flopsHistory.size - 1)
flopsHistory.add(
- FlopsHistoryFragment(
- oldFragment.tick,
+ SimTraceWorkload.Fragment(
+ oldFragment.time,
oldFragment.flops + flops,
oldFragment.duration + traceInterval,
cpuUsage,
@@ -125,22 +131,27 @@ class BitbrainsTraceReader(
val relevantPerformanceInterferenceModelItems =
PerformanceInterferenceModel(
- performanceInterferenceModel.items.filter { it.workloadNames.contains(vmId.toString()) }.toSortedSet()
+ performanceInterferenceModel.items.filter { it.workloadNames.contains(vmId.toString()) }
+ .toSortedSet()
)
val vmWorkload = VmWorkload(
- uuid, "VM Workload $vmId", UnnamedUser,
- VmImage(
+ uuid,
+ "VM Workload $vmId",
+ UnnamedUser,
+ SimWorkloadImage(
uuid,
vmId.toString(),
- mapOf(IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems),
- flopsHistory.asSequence(),
- cores,
- requiredMemory
+ mapOf(
+ IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems,
+ "cores" to cores,
+ "required-memory" to requiredMemory
+ ),
+ SimTraceWorkload(flopsHistory.asSequence())
)
)
entries[vmId] = TraceEntryImpl(
- flopsHistory.firstOrNull()?.tick ?: -1,
+ flopsHistory.firstOrNull()?.time ?: -1,
vmWorkload
)
}
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/gwf/GwfTraceReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/gwf/GwfTraceReader.kt
index 3a4e2e89..a20b4f29 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/gwf/GwfTraceReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/gwf/GwfTraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,19 +20,37 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace.gwf
+package org.opendc.format.trace.gwf
-import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.format.trace.TraceEntry
-import com.atlarge.opendc.format.trace.TraceReader
-import com.atlarge.opendc.workflows.workload.Job
-import com.atlarge.opendc.workflows.workload.Task
-import com.atlarge.opendc.workflows.workload.WORKFLOW_TASK_DEADLINE
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.core.User
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.workload.SimFlopsWorkload
+import org.opendc.workflows.workload.Job
+import org.opendc.workflows.workload.Task
+import org.opendc.workflows.workload.WORKFLOW_TASK_DEADLINE
import java.io.BufferedReader
import java.io.File
import java.io.InputStream
-import java.util.UUID
+import java.util.*
+import kotlin.collections.HashSet
+import kotlin.collections.Iterator
+import kotlin.collections.List
+import kotlin.collections.MutableSet
+import kotlin.collections.component1
+import kotlin.collections.component2
+import kotlin.collections.emptyMap
+import kotlin.collections.filter
+import kotlin.collections.forEach
+import kotlin.collections.getOrPut
+import kotlin.collections.map
+import kotlin.collections.mapIndexed
+import kotlin.collections.mapOf
+import kotlin.collections.mutableMapOf
+import kotlin.collections.set
+import kotlin.collections.sortedBy
+import kotlin.collections.toMap
import kotlin.math.max
import kotlin.math.min
@@ -48,7 +64,7 @@ import kotlin.math.min
*
* @param reader The buffered reader to read the trace with.
*/
-class GwfTraceReader(reader: BufferedReader) : TraceReader<Job> {
+public class GwfTraceReader(reader: BufferedReader) : TraceReader<Job> {
/**
* The internal iterator to use for this reader.
*/
@@ -59,14 +75,14 @@ class GwfTraceReader(reader: BufferedReader) : TraceReader<Job> {
*
* @param file The file to read from.
*/
- constructor(file: File) : this(file.bufferedReader())
+ public constructor(file: File) : this(file.bufferedReader())
/**
* Create a [GwfTraceReader] instance from the specified [InputStream].
*
* @param input The input stream to read from.
*/
- constructor(input: InputStream) : this(input.bufferedReader())
+ public constructor(input: InputStream) : this(input.bufferedReader())
/**
* Initialize the reader.
@@ -120,8 +136,9 @@ class GwfTraceReader(reader: BufferedReader) : TraceReader<Job> {
}
val workflow = entry.workload
val task = Task(
- UUID(0L, taskId), "<unnamed>",
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), flops, cores),
+ UUID(0L, taskId),
+ "<unnamed>",
+ SimWorkloadImage(UUID.randomUUID(), "<unnamed>", emptyMap(), SimFlopsWorkload(flops, cores)),
HashSet(),
mapOf(WORKFLOW_TASK_DEADLINE to runtime)
)
@@ -136,9 +153,11 @@ class GwfTraceReader(reader: BufferedReader) : TraceReader<Job> {
// Fix dependencies and dependents for all tasks
taskDependencies.forEach { (task, dependencies) ->
- (task.dependencies as MutableSet<Task>).addAll(dependencies.map { taskId ->
- tasks[taskId] ?: throw IllegalArgumentException("Dependency task with id $taskId not found")
- })
+ (task.dependencies as MutableSet<Task>).addAll(
+ dependencies.map { taskId ->
+ tasks[taskId] ?: throw IllegalArgumentException("Dependency task with id $taskId not found")
+ }
+ )
}
// Create the entry iterator
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/PerformanceInterferenceEntry.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/PerformanceInterferenceEntry.kt
index ade47e1b..0da1f7c2 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/PerformanceInterferenceEntry.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/PerformanceInterferenceEntry.kt
@@ -1,4 +1,4 @@
-package com.atlarge.opendc.format.trace.sc20
+package org.opendc.format.trace.sc20
internal data class PerformanceInterferenceEntry(
val vms: List<String>,
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20PerformanceInterferenceReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20PerformanceInterferenceReader.kt
index 0e8e1fd2..4267737d 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20PerformanceInterferenceReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20PerformanceInterferenceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,15 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace.sc20
+package org.opendc.format.trace.sc20
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModelItem
-import com.atlarge.opendc.format.trace.PerformanceInterferenceModelReader
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
+import org.opendc.format.trace.PerformanceInterferenceModelReader
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
import java.io.InputStream
-import java.util.TreeSet
+import java.util.*
import kotlin.random.Random
/**
@@ -40,18 +37,18 @@ import kotlin.random.Random
* @param input The input stream to read from.
* @param mapper The Jackson object mapper to use.
*/
-class Sc20PerformanceInterferenceReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) :
+public class Sc20PerformanceInterferenceReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) :
PerformanceInterferenceModelReader {
/**
* The computed value from the file.
*/
- private val items: Map<String, TreeSet<PerformanceInterferenceModelItem>>
+ private val items: Map<String, TreeSet<PerformanceInterferenceModel.Item>>
init {
val entries: List<PerformanceInterferenceEntry> = mapper.readValue(input)
- val res = mutableMapOf<String, TreeSet<PerformanceInterferenceModelItem>>()
+ val res = mutableMapOf<String, TreeSet<PerformanceInterferenceModel.Item>>()
for (entry in entries) {
- val item = PerformanceInterferenceModelItem(TreeSet(entry.vms), entry.minServerLoad, entry.performanceScore)
+ val item = PerformanceInterferenceModel.Item(TreeSet(entry.vms), entry.minServerLoad, entry.performanceScore)
for (workload in entry.vms) {
res.computeIfAbsent(workload) { TreeSet() }.add(item)
}
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20TraceReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20TraceReader.kt
index 8e34505a..66efbcd0 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20TraceReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20TraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +20,20 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace.sc20
+package org.opendc.format.trace.sc20
-import com.atlarge.opendc.compute.core.image.FlopsHistoryFragment
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.core.workload.IMAGE_PERF_INTERFERENCE_MODEL
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.format.trace.TraceEntry
-import com.atlarge.opendc.format.trace.TraceReader
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.core.User
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.interference.IMAGE_PERF_INTERFERENCE_MODEL
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
+import org.opendc.simulator.compute.workload.SimTraceWorkload
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
-import java.util.UUID
+import java.util.*
import kotlin.math.max
import kotlin.math.min
import kotlin.random.Random
@@ -46,7 +44,7 @@ import kotlin.random.Random
* @param traceDirectory The directory of the traces.
* @param performanceInterferenceModel The performance model covering the workload in the VM trace.
*/
-class Sc20TraceReader(
+public class Sc20TraceReader(
traceDirectory: File,
performanceInterferenceModel: PerformanceInterferenceModel,
selectedVms: List<String>,
@@ -66,7 +64,6 @@ class Sc20TraceReader(
val timestampCol = 0
val cpuUsageCol = 1
val coreCol = 12
- val vmIdCol = 19
val provisionedMemoryCol = 20
val traceInterval = 5 * 60 * 1000L
@@ -111,7 +108,7 @@ class Sc20TraceReader(
}
val flopsFragments = sequence {
- var last: FlopsHistoryFragment? = null
+ var last: SimTraceWorkload.Fragment? = null
BufferedReader(FileReader(vmFile)).use { reader ->
reader.lineSequence()
@@ -132,8 +129,8 @@ class Sc20TraceReader(
last = if (last != null && last!!.flops == 0L && flops == 0L) {
val oldFragment = last!!
- FlopsHistoryFragment(
- oldFragment.tick,
+ SimTraceWorkload.Fragment(
+ oldFragment.time,
oldFragment.flops + flops,
oldFragment.duration + traceInterval,
cpuUsage,
@@ -141,7 +138,7 @@ class Sc20TraceReader(
)
} else {
val fragment =
- FlopsHistoryFragment(timestamp, flops, traceInterval, cpuUsage, cores)
+ SimTraceWorkload.Fragment(timestamp, flops, traceInterval, cpuUsage, cores)
if (last != null) {
yield(last!!)
}
@@ -164,14 +161,18 @@ class Sc20TraceReader(
Random(random.nextInt())
)
val vmWorkload = VmWorkload(
- uuid, "VM Workload $vmId", UnnamedUser,
- VmImage(
+ uuid,
+ "VM Workload $vmId",
+ UnnamedUser,
+ SimWorkloadImage(
uuid,
vmId,
- mapOf(IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems),
- flopsFragments.asSequence(),
- maxCores,
- requiredMemory
+ mapOf(
+ IMAGE_PERF_INTERFERENCE_MODEL to relevantPerformanceInterferenceModelItems,
+ "cores" to cores,
+ "required-memory" to requiredMemory
+ ),
+ SimTraceWorkload(flopsFragments.asSequence())
)
)
entries[uuid] = TraceEntryImpl(
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20VmPlacementReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20VmPlacementReader.kt
index 5295ae03..61bdea60 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/sc20/Sc20VmPlacementReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/sc20/Sc20VmPlacementReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace.sc20
+package org.opendc.format.trace.sc20
-import com.atlarge.opendc.format.trace.VmPlacementReader
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
+import org.opendc.format.trace.VmPlacementReader
import java.io.InputStream
/**
@@ -36,7 +34,7 @@ import java.io.InputStream
* @param input The input stream to read from.
* @param mapper The Jackson object mapper to use.
*/
-class Sc20VmPlacementReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) :
+public class Sc20VmPlacementReader(input: InputStream, mapper: ObjectMapper = jacksonObjectMapper()) :
VmPlacementReader {
/**
* The environment that was read from the file.
diff --git a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/swf/SwfTraceReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/swf/SwfTraceReader.kt
index 2f6ce238..52d41c44 100644
--- a/simulator/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/swf/SwfTraceReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/swf/SwfTraceReader.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.format.trace.swf
+package org.opendc.format.trace.swf
-import com.atlarge.opendc.compute.core.image.FlopsHistoryFragment
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.core.workload.VmWorkload
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.format.trace.TraceEntry
-import com.atlarge.opendc.format.trace.TraceReader
+import org.opendc.compute.core.workload.VmWorkload
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.core.User
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.workload.SimTraceWorkload
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
-import java.util.UUID
+import java.util.*
/**
* A [TraceReader] for reading SWF traces into VM-modeled workloads.
@@ -42,7 +40,7 @@ import java.util.UUID
*
* @param file The trace file.
*/
-class SwfTraceReader(
+public class SwfTraceReader(
file: File,
maxNumCores: Int = -1
) : TraceReader<VmWorkload> {
@@ -66,17 +64,17 @@ class SwfTraceReader(
val sliceDuration = 5 * 60L
- var jobNumber = -1L
- var submitTime = -1L
- var waitTime = -1L
- var runTime = -1L
- var cores = -1
- var memory = -1L
- var slicedWaitTime = -1L
- var flopsPerSecond = -1L
- var flopsPartialSlice = -1L
- var flopsFullSlice = -1L
- var runtimePartialSliceRemainder = -1L
+ var jobNumber: Long
+ var submitTime: Long
+ var waitTime: Long
+ var runTime: Long
+ var cores: Int
+ var memory: Long
+ var slicedWaitTime: Long
+ var flopsPerSecond: Long
+ var flopsPartialSlice: Long
+ var flopsFullSlice: Long
+ var runtimePartialSliceRemainder: Long
BufferedReader(FileReader(file)).use { reader ->
reader.lineSequence()
@@ -105,7 +103,7 @@ class SwfTraceReader(
memory /= 1000 // convert KB to MB
}
- val flopsHistory = mutableListOf<FlopsHistoryFragment>()
+ val flopsHistory = mutableListOf<SimTraceWorkload.Fragment>()
// Insert waiting time slices
@@ -114,8 +112,12 @@ class SwfTraceReader(
if (waitTime >= sliceDuration) {
for (tick in submitTime until (submitTime + waitTime - sliceDuration) step sliceDuration) {
flopsHistory.add(
- FlopsHistoryFragment(
- tick * 1000L, 0L, sliceDuration * 1000L, 0.0, cores
+ SimTraceWorkload.Fragment(
+ tick * 1000L,
+ 0L,
+ sliceDuration * 1000L,
+ 0.0,
+ cores
)
)
slicedWaitTime += sliceDuration
@@ -129,19 +131,25 @@ class SwfTraceReader(
flopsPartialSlice = flopsPerSecond * runtimePartialSliceRemainder
flopsFullSlice = flopsPerSecond * runTime - flopsPartialSlice
- for (tick in (submitTime + slicedWaitTime)
- until (submitTime + slicedWaitTime + runTime - sliceDuration)
- step sliceDuration) {
+ for (
+ tick in (submitTime + slicedWaitTime)
+ until (submitTime + slicedWaitTime + runTime - sliceDuration)
+ step sliceDuration
+ ) {
flopsHistory.add(
- FlopsHistoryFragment(
- tick * 1000L, flopsFullSlice / sliceDuration, sliceDuration * 1000L, 1.0, cores
+ SimTraceWorkload.Fragment(
+ tick * 1000L,
+ flopsFullSlice / sliceDuration,
+ sliceDuration * 1000L,
+ 1.0,
+ cores
)
)
}
if (runtimePartialSliceRemainder > 0) {
flopsHistory.add(
- FlopsHistoryFragment(
+ SimTraceWorkload.Fragment(
submitTime + (slicedWaitTime + runTime - runtimePartialSliceRemainder),
flopsPartialSlice,
sliceDuration,
@@ -153,14 +161,17 @@ class SwfTraceReader(
val uuid = UUID(0L, jobNumber)
val vmWorkload = VmWorkload(
- uuid, "SWF Workload $jobNumber", UnnamedUser,
- VmImage(
+ uuid,
+ "SWF Workload $jobNumber",
+ UnnamedUser,
+ SimWorkloadImage(
uuid,
jobNumber.toString(),
- emptyMap(),
- flopsHistory.asSequence(),
- cores,
- memory
+ mapOf(
+ "cores" to cores,
+ "required-memory" to memory
+ ),
+ SimTraceWorkload(flopsHistory.asSequence())
)
)
diff --git a/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/wtf/WtfTraceReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/wtf/WtfTraceReader.kt
new file mode 100644
index 00000000..b2931468
--- /dev/null
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/trace/wtf/WtfTraceReader.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.format.trace.wtf
+
+import org.apache.avro.generic.GenericRecord
+import org.apache.hadoop.fs.Path
+import org.apache.parquet.avro.AvroParquetReader
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.core.User
+import org.opendc.format.trace.TraceEntry
+import org.opendc.format.trace.TraceReader
+import org.opendc.simulator.compute.workload.SimFlopsWorkload
+import org.opendc.workflows.workload.Job
+import org.opendc.workflows.workload.Task
+import org.opendc.workflows.workload.WORKFLOW_TASK_DEADLINE
+import java.util.UUID
+import kotlin.math.min
+
+/**
+ * A [TraceReader] for the Workflow Trace Format (WTF). See the Workflow Trace Archive
+ * (https://wta.atlarge-research.com/) for more information about the format.
+ *
+ * @param path The path to the trace.
+ */
+public class WtfTraceReader(path: String) : TraceReader<Job> {
+ /**
+ * The internal iterator to use for this reader.
+ */
+ private val iterator: Iterator<TraceEntry<Job>>
+
+ /**
+ * Initialize the reader.
+ */
+ init {
+ val entries = mutableMapOf<Long, TraceEntryImpl>()
+ val tasks = mutableMapOf<Long, Task>()
+ val taskDependencies = mutableMapOf<Task, List<Long>>()
+
+ val reader = AvroParquetReader.builder<GenericRecord>(Path(path, "tasks/schema-1.0")).build()
+
+ while (true) {
+ val nextRecord = reader.read() ?: break
+
+ val workflowId = nextRecord.get("workflow_id") as Long
+ val taskId = nextRecord.get("id") as Long
+ val submitTime = nextRecord.get("ts_submit") as Long
+ val runtime = nextRecord.get("runtime") as Long
+ val cores = (nextRecord.get("resource_amount_requested") as Double).toInt()
+ @Suppress("UNCHECKED_CAST")
+ val dependencies = (nextRecord.get("parents") as ArrayList<GenericRecord>).map {
+ it.get("item") as Long
+ }
+
+ val flops: Long = 4100 * (runtime / 1000) * cores
+
+ val entry = entries.getOrPut(workflowId) {
+ TraceEntryImpl(submitTime, Job(UUID(0L, taskId), "<unnamed>", UnnamedUser, HashSet()))
+ }
+ val workflow = entry.workload
+ val task = Task(
+ UUID(0L, taskId),
+ "<unnamed>",
+ SimWorkloadImage(UUID.randomUUID(), "<unnamed>", emptyMap(), SimFlopsWorkload(flops, cores)),
+ HashSet(),
+ mapOf(WORKFLOW_TASK_DEADLINE to runtime)
+ )
+
+ entry.submissionTime = min(entry.submissionTime, submitTime)
+ (workflow.tasks as MutableSet<Task>).add(task)
+ tasks[taskId] = task
+ taskDependencies[task] = dependencies
+ }
+
+ // Fix dependencies and dependents for all tasks
+ taskDependencies.forEach { (task, dependencies) ->
+ (task.dependencies as MutableSet<Task>).addAll(
+ dependencies.map { taskId ->
+ tasks[taskId] ?: throw IllegalArgumentException("Dependency task with id $taskId not found")
+ }
+ )
+ }
+
+ // Create the entry iterator
+ iterator = entries.values.sortedBy { it.submissionTime }.iterator()
+ }
+
+ override fun hasNext(): Boolean = iterator.hasNext()
+
+ override fun next(): TraceEntry<Job> = iterator.next()
+
+ override fun close() {}
+
+ /**
+ * An unnamed user.
+ */
+ private object UnnamedUser : User {
+ override val name: String = "<unnamed>"
+ override val uid: UUID = UUID.randomUUID()
+ }
+
+ /**
+ * An entry in the trace.
+ */
+ private data class TraceEntryImpl(
+ override var submissionTime: Long,
+ override val workload: Job
+ ) : TraceEntry<Job>
+}
diff --git a/simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/swf/SwfTraceReaderTest.kt b/simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/swf/SwfTraceReaderTest.kt
new file mode 100644
index 00000000..8db2ab40
--- /dev/null
+++ b/simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/swf/SwfTraceReaderTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.format.trace.swf
+
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.opendc.compute.simulator.SimWorkloadImage
+import org.opendc.simulator.compute.workload.SimTraceWorkload
+import java.io.File
+
+class SwfTraceReaderTest {
+ @Test
+ internal fun testParseSwf() {
+ val reader = SwfTraceReader(File(SwfTraceReaderTest::class.java.getResource("/swf_trace.txt").toURI()))
+ var entry = reader.next()
+ assertEquals(0, entry.submissionTime)
+ // 1961 slices for waiting, 3 full and 1 partial running slices
+ assertEquals(1965, ((entry.workload.image as SimWorkloadImage).workload as SimTraceWorkload).trace.toList().size)
+
+ entry = reader.next()
+ assertEquals(164472, entry.submissionTime)
+ // 1188 slices for waiting, 0 full and 1 partial running slices
+ assertEquals(1189, ((entry.workload.image as SimWorkloadImage).workload as SimTraceWorkload).trace.toList().size)
+ assertEquals(5_100_000L, ((entry.workload.image as SimWorkloadImage).workload as SimTraceWorkload).trace.toList().last().flops)
+ assertEquals(0.25, ((entry.workload.image as SimWorkloadImage).workload as SimTraceWorkload).trace.toList().last().usage)
+ }
+}
diff --git a/simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/wtf/WtfTraceReaderTest.kt b/simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/wtf/WtfTraceReaderTest.kt
new file mode 100644
index 00000000..58d96657
--- /dev/null
+++ b/simulator/opendc-format/src/test/kotlin/org/opendc/format/trace/wtf/WtfTraceReaderTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.format.trace.wtf
+
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Test
+
+/**
+ * Test suite for the [WtfTraceReader] class.
+ */
+class WtfTraceReaderTest {
+ /**
+ * Smoke test for parsing WTF traces.
+ */
+ @Test
+ fun testParseWtf() {
+ val reader = WtfTraceReader("src/test/resources/wtf-trace")
+ var entry = reader.next()
+ assertEquals(0, entry.submissionTime)
+ assertEquals(23, entry.workload.tasks.size)
+
+ entry = reader.next()
+ assertEquals(333387, entry.submissionTime)
+ assertEquals(23, entry.workload.tasks.size)
+ }
+}
diff --git a/simulator/opendc/opendc-format/src/test/resources/swf_trace.txt b/simulator/opendc-format/src/test/resources/swf_trace.txt
index c3ecf890..c3ecf890 100644
--- a/simulator/opendc/opendc-format/src/test/resources/swf_trace.txt
+++ b/simulator/opendc-format/src/test/resources/swf_trace.txt
diff --git a/simulator/opendc-format/src/test/resources/wtf-trace/tasks/schema-1.0/part.0.parquet b/simulator/opendc-format/src/test/resources/wtf-trace/tasks/schema-1.0/part.0.parquet
new file mode 100644
index 00000000..d2044038
--- /dev/null
+++ b/simulator/opendc-format/src/test/resources/wtf-trace/tasks/schema-1.0/part.0.parquet
Binary files differ
diff --git a/simulator/opendc/opendc-runner-web/build.gradle.kts b/simulator/opendc-runner-web/build.gradle.kts
index 6f725de1..cf437843 100644
--- a/simulator/opendc/opendc-runner-web/build.gradle.kts
+++ b/simulator/opendc-runner-web/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,14 +29,16 @@ plugins {
}
application {
- mainClassName = "com.atlarge.opendc.runner.web.MainKt"
+ mainClassName = "org.opendc.runner.web.MainKt"
}
dependencies {
- api(project(":opendc:opendc-core"))
- implementation(project(":opendc:opendc-compute"))
- implementation(project(":opendc:opendc-format"))
- implementation(project(":opendc:opendc-experiments-sc20"))
+ api(project(":opendc-core"))
+ implementation(project(":opendc-compute:opendc-compute-simulator"))
+ implementation(project(":opendc-format"))
+ implementation(project(":opendc-experiments:opendc-experiments-sc20"))
+ implementation(project(":opendc-simulator:opendc-simulator-core"))
+ implementation(project(":opendc-simulator:opendc-simulator-compute"))
implementation("com.github.ajalt:clikt:2.8.0")
implementation("io.github.microutils:kotlin-logging:1.7.10")
@@ -49,7 +49,6 @@ dependencies {
exclude(group = "log4j")
}
- runtimeOnly(project(":odcsim:odcsim-engine-omega"))
runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:2.13.1")
runtimeOnly("org.apache.logging.log4j:log4j-1.2-api:2.13.1")
}
diff --git a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/Main.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt
index 807c119e..26577ef2 100644
--- a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/Main.kt
+++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt
@@ -1,16 +1,27 @@
-package com.atlarge.opendc.runner.web
-
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.opendc.compute.virt.service.allocation.*
-import com.atlarge.opendc.experiments.sc20.experiment.attachMonitor
-import com.atlarge.opendc.experiments.sc20.experiment.createFailureDomain
-import com.atlarge.opendc.experiments.sc20.experiment.createProvisioner
-import com.atlarge.opendc.experiments.sc20.experiment.model.Workload
-import com.atlarge.opendc.experiments.sc20.experiment.monitor.ParquetExperimentMonitor
-import com.atlarge.opendc.experiments.sc20.experiment.processTrace
-import com.atlarge.opendc.experiments.sc20.trace.Sc20ParquetTraceReader
-import com.atlarge.opendc.experiments.sc20.trace.Sc20RawParquetTraceReader
-import com.atlarge.opendc.format.trace.sc20.Sc20PerformanceInterferenceReader
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.runner.web
+
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.types.file
@@ -22,25 +33,32 @@ import com.mongodb.client.MongoClients
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoDatabase
import com.mongodb.client.model.Filters
-import java.io.File
-import java.util.*
-import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.test.TestCoroutineScope
import mu.KotlinLogging
import org.bson.Document
+import org.opendc.compute.simulator.allocation.*
+import org.opendc.experiments.sc20.experiment.attachMonitor
+import org.opendc.experiments.sc20.experiment.createFailureDomain
+import org.opendc.experiments.sc20.experiment.createProvisioner
+import org.opendc.experiments.sc20.experiment.model.Workload
+import org.opendc.experiments.sc20.experiment.monitor.ParquetExperimentMonitor
+import org.opendc.experiments.sc20.experiment.processTrace
+import org.opendc.experiments.sc20.trace.Sc20ParquetTraceReader
+import org.opendc.experiments.sc20.trace.Sc20RawParquetTraceReader
+import org.opendc.format.trace.sc20.Sc20PerformanceInterferenceReader
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import java.io.File
+import kotlin.random.Random
private val logger = KotlinLogging.logger {}
/**
- * The provider for the simulation engine to use.
- */
-private val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
-
-/**
* Represents the CLI command for starting the OpenDC web runner.
*/
-class RunnerCli : CliktCommand(name = "runner") {
+@OptIn(ExperimentalCoroutinesApi::class)
+public class RunnerCli : CliktCommand(name = "runner") {
/**
* The name of the database to use.
*/
@@ -195,8 +213,8 @@ class RunnerCli : CliktCommand(name = "runner") {
val workloadFraction = traceDocument.get("loadSamplingFraction", Number::class.java).toDouble()
val seeder = Random(seed)
- val system = provider("experiment-$id")
- val root = system.newDomain("root")
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
val chan = Channel<Unit>(Channel.CONFLATED)
@@ -230,9 +248,10 @@ class RunnerCli : CliktCommand(name = "runner") {
4096
)
- root.launch {
+ testScope.launch {
val (bareMetalProvisioner, scheduler) = createProvisioner(
- root,
+ this,
+ clock,
environment,
allocationPolicy
)
@@ -240,6 +259,8 @@ class RunnerCli : CliktCommand(name = "runner") {
val failureDomain = if (operational.getBoolean("failuresEnabled")) {
logger.debug("ENABLING failures")
createFailureDomain(
+ testScope,
+ clock,
seeder.nextInt(),
operational.get("failureFrequency", Number::class.java)?.toDouble() ?: 24.0 * 7,
bareMetalProvisioner,
@@ -249,13 +270,14 @@ class RunnerCli : CliktCommand(name = "runner") {
null
}
- attachMonitor(scheduler, monitor)
+ attachMonitor(this, clock, scheduler, monitor)
processTrace(
+ this,
+ clock,
trace,
scheduler,
chan,
- monitor,
- emptyMap()
+ monitor
)
logger.debug("SUBMIT=${scheduler.submittedVms}")
@@ -269,17 +291,16 @@ class RunnerCli : CliktCommand(name = "runner") {
}
try {
- system.run()
+ testScope.advanceUntilIdle()
} finally {
- system.terminate()
monitor.close()
}
}
- val POLL_INTERVAL = 5000L // ms = 5 s
- val HEARTBEAT_INTERVAL = 60000L // ms = 1 min
+ private val POLL_INTERVAL = 5000L // ms = 5 s
+ private val HEARTBEAT_INTERVAL = 60000L // ms = 1 min
- override fun run() = runBlocking(Dispatchers.Default) {
+ override fun run(): Unit = runBlocking(Dispatchers.Default) {
logger.info { "Starting OpenDC web runner" }
logger.info { "Connecting to MongoDB instance" }
val database = createDatabase()
@@ -342,4 +363,4 @@ class RunnerCli : CliktCommand(name = "runner") {
/**
* Main entry point of the runner.
*/
-fun main(args: Array<String>) = RunnerCli().main(args)
+public fun main(args: Array<String>): Unit = RunnerCli().main(args)
diff --git a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/ResultProcessor.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/ResultProcessor.kt
index 39092653..f9a3cd2b 100644
--- a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/ResultProcessor.kt
+++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/ResultProcessor.kt
@@ -1,20 +1,42 @@
-package com.atlarge.opendc.runner.web
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.runner.web
-import java.io.File
import org.apache.spark.sql.Column
import org.apache.spark.sql.Dataset
import org.apache.spark.sql.Row
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions.*
+import java.io.File
/**
* A helper class for processing the experiment results using Apache Spark.
*/
-class ResultProcessor(private val master: String, private val outputPath: File) {
+public class ResultProcessor(private val master: String, private val outputPath: File) {
/**
* Process the results of the scenario with the given [id].
*/
- fun process(id: String): Result {
+ public fun process(id: String): Result {
val spark = SparkSession.builder()
.master(master)
.appName("opendc-simulator-$id")
@@ -48,22 +70,22 @@ class ResultProcessor(private val master: String, private val outputPath: File)
}
}
- data class Result(
- val totalRequestedBurst: List<Long>,
- val totalGrantedBurst: List<Long>,
- val totalOvercommittedBurst: List<Long>,
- val totalInterferedBurst: List<Long>,
- val meanCpuUsage: List<Double>,
- val meanCpuDemand: List<Double>,
- val meanNumDeployedImages: List<Double>,
- val maxNumDeployedImages: List<Int>,
- val totalPowerDraw: List<Long>,
- val totalFailureSlices: List<Long>,
- val totalFailureVmSlices: List<Long>,
- val totalVmsSubmitted: List<Int>,
- val totalVmsQueued: List<Int>,
- val totalVmsFinished: List<Int>,
- val totalVmsFailed: List<Int>
+ public data class Result(
+ public val totalRequestedBurst: List<Long>,
+ public val totalGrantedBurst: List<Long>,
+ public val totalOvercommittedBurst: List<Long>,
+ public val totalInterferedBurst: List<Long>,
+ public val meanCpuUsage: List<Double>,
+ public val meanCpuDemand: List<Double>,
+ public val meanNumDeployedImages: List<Double>,
+ public val maxNumDeployedImages: List<Int>,
+ public val totalPowerDraw: List<Long>,
+ public val totalFailureSlices: List<Long>,
+ public val totalFailureVmSlices: List<Long>,
+ public val totalVmsSubmitted: List<Int>,
+ public val totalVmsQueued: List<Int>,
+ public val totalVmsFinished: List<Int>,
+ public val totalVmsFailed: List<Int>
)
/**
@@ -169,19 +191,25 @@ class ResultProcessor(private val master: String, private val outputPath: File)
}
// Spark helper functions
- operator fun Column.times(other: Column): Column = `$times`(other)
- operator fun Column.div(other: Column): Column = `$div`(other)
- operator fun Column.get(other: Column): Column = this.apply(other)
+ private operator fun Column.times(other: Column): Column = `$times`(other)
+ private operator fun Column.div(other: Column): Column = `$div`(other)
+ private operator fun Column.get(other: Column): Column = this.apply(other)
- val sliceLength = 5 * 60 * 1000
- val states = map(
- lit("ERROR"), lit(1),
- lit("ACTIVE"), lit(0),
- lit("SHUTOFF"), lit(0)
+ private val sliceLength = 5 * 60 * 1000
+ private val states = map(
+ lit("ERROR"),
+ lit(1),
+ lit("ACTIVE"),
+ lit(0),
+ lit("SHUTOFF"),
+ lit(0)
)
- val oppositeStates = map(
- lit("ERROR"), lit(0),
- lit("ACTIVE"), lit(1),
- lit("SHUTOFF"), lit(1)
+ private val oppositeStates = map(
+ lit("ERROR"),
+ lit(0),
+ lit("ACTIVE"),
+ lit(1),
+ lit("SHUTOFF"),
+ lit(1)
)
}
diff --git a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/ScenarioManager.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/ScenarioManager.kt
index 40ffd282..504fccdc 100644
--- a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/ScenarioManager.kt
+++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/ScenarioManager.kt
@@ -1,19 +1,41 @@
-package com.atlarge.opendc.runner.web
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.runner.web
import com.mongodb.client.MongoCollection
import com.mongodb.client.model.Filters
import com.mongodb.client.model.Updates
-import java.time.Instant
import org.bson.Document
+import java.time.Instant
/**
* Manages the queue of scenarios that need to be processed.
*/
-class ScenarioManager(private val collection: MongoCollection<Document>) {
+public class ScenarioManager(private val collection: MongoCollection<Document>) {
/**
* Find the next scenario that the simulator needs to process.
*/
- fun findNext(): Document? {
+ public fun findNext(): Document? {
return collection
.find(Filters.eq("simulation.state", "QUEUED"))
.first()
@@ -22,7 +44,7 @@ class ScenarioManager(private val collection: MongoCollection<Document>) {
/**
* Claim the scenario in the database with the specified id.
*/
- fun claim(id: String): Boolean {
+ public fun claim(id: String): Boolean {
val res = collection.findOneAndUpdate(
Filters.and(
Filters.eq("_id", id),
@@ -39,7 +61,7 @@ class ScenarioManager(private val collection: MongoCollection<Document>) {
/**
* Update the heartbeat of the specified scenario.
*/
- fun heartbeat(id: String) {
+ public fun heartbeat(id: String) {
collection.findOneAndUpdate(
Filters.and(
Filters.eq("_id", id),
@@ -52,7 +74,7 @@ class ScenarioManager(private val collection: MongoCollection<Document>) {
/**
* Mark the scenario as failed.
*/
- fun fail(id: String) {
+ public fun fail(id: String) {
collection.findOneAndUpdate(
Filters.eq("_id", id),
Updates.combine(
@@ -65,7 +87,7 @@ class ScenarioManager(private val collection: MongoCollection<Document>) {
/**
* Persist the specified results.
*/
- fun finish(id: String, result: ResultProcessor.Result) {
+ public fun finish(id: String, result: ResultProcessor.Result) {
collection.findOneAndUpdate(
Filters.eq("_id", id),
Updates.combine(
diff --git a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/TopologyParser.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt
index 499585ec..5e483271 100644
--- a/simulator/opendc/opendc-runner-web/src/main/kotlin/com/atlarge/opendc/runner/web/TopologyParser.kt
+++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt
@@ -1,42 +1,65 @@
-package com.atlarge.opendc.runner.web
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.runner.web
-import com.atlarge.odcsim.Domain
-import com.atlarge.opendc.compute.core.MemoryUnit
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.metal.NODE_CLUSTER
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import com.atlarge.opendc.compute.metal.power.LinearLoadPowerModel
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.compute.metal.service.SimpleProvisioningService
-import com.atlarge.opendc.core.Environment
-import com.atlarge.opendc.core.Platform
-import com.atlarge.opendc.core.Zone
-import com.atlarge.opendc.core.services.ServiceRegistry
-import com.atlarge.opendc.format.environment.EnvironmentReader
import com.mongodb.client.AggregateIterable
import com.mongodb.client.MongoCollection
import com.mongodb.client.model.Aggregates
import com.mongodb.client.model.Field
import com.mongodb.client.model.Filters
import com.mongodb.client.model.Projections
-import java.util.*
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.bson.Document
+import org.opendc.compute.core.metal.NODE_CLUSTER
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.compute.core.metal.service.SimpleProvisioningService
+import org.opendc.compute.simulator.SimBareMetalDriver
+import org.opendc.compute.simulator.power.LinearLoadPowerModel
+import org.opendc.core.Environment
+import org.opendc.core.Platform
+import org.opendc.core.Zone
+import org.opendc.core.services.ServiceRegistry
+import org.opendc.format.environment.EnvironmentReader
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
+import java.time.Clock
+import java.util.*
/**
* A helper class that converts the MongoDB topology into an OpenDC environment.
*/
-class TopologyParser(private val collection: MongoCollection<Document>, private val id: String) : EnvironmentReader {
+public class TopologyParser(private val collection: MongoCollection<Document>, private val id: String) : EnvironmentReader {
/**
* Parse the topology with the specified [id].
*/
- override suspend fun construct(dom: Domain): Environment {
- val nodes = mutableListOf<SimpleBareMetalDriver>()
+ override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
+ val nodes = mutableListOf<SimBareMetalDriver>()
val random = Random(0)
for (machine in fetchMachines(id)) {
- val machineId = machine.getString("_id")
val clusterId = machine.getString("rack_id")
val position = machine.getInteger("position")
@@ -58,13 +81,13 @@ class TopologyParser(private val collection: MongoCollection<Document>, private
)
}
nodes.add(
- SimpleBareMetalDriver(
- dom.newDomain(machineId),
+ SimBareMetalDriver(
+ coroutineScope,
+ clock,
UUID(random.nextLong(), random.nextLong()),
"node-$clusterId-$position",
mapOf(NODE_CLUSTER to clusterId),
- processors,
- memoryUnits,
+ SimMachineModel(processors, memoryUnits),
// For now we assume a simple linear load model with an idle draw of ~200W and a maximum
// power draw of 350W.
// Source: https://stackoverflow.com/questions/6128960
@@ -73,8 +96,8 @@ class TopologyParser(private val collection: MongoCollection<Document>, private
)
}
- val provisioningService = SimpleProvisioningService(dom.newDomain("provisioner"))
- dom.launch {
+ val provisioningService = SimpleProvisioningService()
+ coroutineScope.launch {
for (node in nodes) {
provisioningService.create(node)
}
@@ -83,7 +106,9 @@ class TopologyParser(private val collection: MongoCollection<Document>, private
val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
val platform = Platform(
- UUID.randomUUID(), "opendc-platform", listOf(
+ UUID.randomUUID(),
+ "opendc-platform",
+ listOf(
Zone(UUID.randomUUID(), "zone", serviceRegistry)
)
)
diff --git a/simulator/opendc/opendc-runner-web/src/main/resources/log4j2.xml b/simulator/opendc-runner-web/src/main/resources/log4j2.xml
index 1d873554..16cedf34 100644
--- a/simulator/opendc/opendc-runner-web/src/main/resources/log4j2.xml
+++ b/simulator/opendc-runner-web/src/main/resources/log4j2.xml
@@ -26,17 +26,14 @@
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} [%highlight{%-5level}] %logger{36} - %msg%n" disableAnsi="false" />
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} [%highlight{%-5level}] %logger{36} - %msg%n" disableAnsi="false"/>
</Console>
</Appenders>
<Loggers>
- <Logger name="com.atlarge.odcsim" level="info" additivity="false">
+ <Logger name="org.opendc" level="warn" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
- <Logger name="com.atlarge.opendc" level="warn" additivity="false">
- <AppenderRef ref="Console"/>
- </Logger>
- <Logger name="com.atlarge.opendc.runner" level="info" additivity="false">
+ <Logger name="org.opendc.runner" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.apache.hadoop" level="warn" additivity="false">
diff --git a/simulator/opendc-simulator/build.gradle.kts b/simulator/opendc-simulator/build.gradle.kts
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/simulator/opendc-simulator/build.gradle.kts
diff --git a/simulator/odcsim/odcsim-api/build.gradle.kts b/simulator/opendc-simulator/opendc-simulator-compute/build.gradle.kts
index c8c6c90c..cd7e5706 100644
--- a/simulator/odcsim/odcsim-api/build.gradle.kts
+++ b/simulator/opendc-simulator/opendc-simulator-compute/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2017 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,14 @@
* SOFTWARE.
*/
-description = "Framework for discrete event simulation in Kotlin"
+description = "Library for simulation of cloud computing components"
-/* Build configuration */
plugins {
`kotlin-library-convention`
}
dependencies {
- implementation(kotlin("stdlib"))
- api("org.slf4j:slf4j-api:${Library.SLF4J}")
- api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Library.KOTLINX_COROUTINES}")
+ api(project(":opendc-simulator:opendc-simulator-core"))
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
new file mode 100644
index 00000000..c6d5bdd1
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.intrinsics.startCoroutineCancellable
+import kotlinx.coroutines.selects.SelectClause0
+import kotlinx.coroutines.selects.SelectInstance
+import org.opendc.simulator.compute.workload.SimWorkload
+import java.lang.Runnable
+import java.time.Clock
+import kotlin.coroutines.ContinuationInterceptor
+import kotlin.math.ceil
+import kotlin.math.max
+import kotlin.math.min
+
+/**
+ * A simulated bare-metal machine that is able to run a single workload.
+ *
+ * A [SimBareMetalMachine] is a stateful object and you should be careful when operating this object concurrently. For
+ * example. the class expects only a single concurrent call to [run].
+ *
+ * @param coroutineScope The [CoroutineScope] to run the simulated workload in.
+ * @param clock The virtual clock to track the simulation time.
+ * @param model The machine model to simulate.
+ */
+@OptIn(ExperimentalCoroutinesApi::class, InternalCoroutinesApi::class)
+public class SimBareMetalMachine(
+ private val coroutineScope: CoroutineScope,
+ private val clock: Clock,
+ override val model: SimMachineModel
+) : SimMachine {
+ /**
+ * A [StateFlow] representing the CPU usage of the simulated machine.
+ */
+ override val usage: StateFlow<Double>
+ get() = usageState
+
+ /**
+ * The current active workload.
+ */
+ private var activeWorkload: SimWorkload? = null
+
+ /**
+ * Run the specified [SimWorkload] on this machine and suspend execution util the workload has finished.
+ */
+ override suspend fun run(workload: SimWorkload) {
+ require(activeWorkload == null) { "Run should not be called concurrently" }
+
+ try {
+ activeWorkload = workload
+ workload.run(ctx)
+ } finally {
+ activeWorkload = null
+ }
+ }
+
+ /**
+ * The execution context in which the workload runs.
+ */
+ private val ctx = object : SimExecutionContext {
+ override val machine: SimMachineModel
+ get() = this@SimBareMetalMachine.model
+
+ override val clock: Clock
+ get() = this@SimBareMetalMachine.clock
+
+ override fun onRun(
+ batch: Sequence<SimExecutionContext.Slice>,
+ triggerMode: SimExecutionContext.TriggerMode,
+ merge: (SimExecutionContext.Slice, SimExecutionContext.Slice) -> SimExecutionContext.Slice
+ ): SelectClause0 {
+ return object : SelectClause0 {
+ @InternalCoroutinesApi
+ override fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R) {
+ // Do not reset the usage state: we will set it ourselves
+ usageFlush?.dispose()
+ usageFlush = null
+
+ val queue = batch.iterator()
+ var start = Long.MIN_VALUE
+ var currentWork: SliceWork? = null
+ var currentDisposable: DisposableHandle? = null
+
+ fun schedule(slice: SimExecutionContext.Slice) {
+ start = clock.millis()
+
+ val isLastSlice = !queue.hasNext()
+ val work = SliceWork(slice)
+ val candidateDuration = when (triggerMode) {
+ SimExecutionContext.TriggerMode.FIRST -> work.minExit
+ SimExecutionContext.TriggerMode.LAST -> work.maxExit
+ SimExecutionContext.TriggerMode.DEADLINE -> slice.deadline - start
+ }
+
+ // Check whether the deadline is exceeded during the run of the slice.
+ val duration = min(candidateDuration, slice.deadline - start)
+
+ val action = Runnable {
+ currentWork = null
+
+ // Flush all the work that was performed
+ val hasFinished = work.stop(duration)
+
+ if (!isLastSlice) {
+ val candidateSlice = queue.next()
+ val nextSlice =
+ // If our previous slice exceeds its deadline, merge it with the next candidate slice
+ if (hasFinished)
+ candidateSlice
+ else
+ merge(candidateSlice, slice)
+ schedule(nextSlice)
+ } else if (select.trySelect()) {
+ block.startCoroutineCancellable(select.completion)
+ }
+ }
+
+ // Schedule the flush after the entire slice has finished
+ currentDisposable = delay.invokeOnTimeout(duration, action)
+
+ // Start the slice work
+ currentWork = work
+ work.start()
+ }
+
+ // Schedule the first work
+ if (queue.hasNext()) {
+ schedule(queue.next())
+
+ // A DisposableHandle to flush the work in case the call is cancelled
+ val disposable = DisposableHandle {
+ val end = clock.millis()
+ val duration = end - start
+
+ currentWork?.stop(duration)
+ currentDisposable?.dispose()
+
+ // Schedule reset the usage of the machine since the call is returning
+ usageFlush = delay.invokeOnTimeout(1) {
+ usageState.value = 0.0
+ usageFlush = null
+ }
+ }
+
+ select.disposeOnSelect(disposable)
+ } else if (select.trySelect()) {
+ // No work has been given: select immediately
+ block.startCoroutineCancellable(select.completion)
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * The [MutableStateFlow] containing the load of the server.
+ */
+ private val usageState = MutableStateFlow(0.0)
+
+ /**
+ * A disposable to prevent resetting the usage state for subsequent calls to onRun.
+ */
+ private var usageFlush: DisposableHandle? = null
+
+ /**
+ * Cache the [Delay] instance for timing.
+ *
+ * XXX We need to cache this before the call to [onRun] since doing this in [onRun] is too heavy.
+ * XXX Note however that this is an ugly hack which may break in the future.
+ */
+ @OptIn(InternalCoroutinesApi::class)
+ private val delay = coroutineScope.coroutineContext[ContinuationInterceptor] as Delay
+
+ /**
+ * A slice to be processed.
+ */
+ private inner class SliceWork(val slice: SimExecutionContext.Slice) {
+ /**
+ * The duration after which the first processor finishes processing this slice.
+ */
+ val minExit: Long
+
+ /**
+ * The duration after which the last processor finishes processing this slice.
+ */
+ val maxExit: Long
+
+ /**
+ * A flag to indicate that the slice will exceed the deadline.
+ */
+ val exceedsDeadline: Boolean
+ get() = slice.deadline < maxExit
+
+ /**
+ * The total amount of CPU usage.
+ */
+ val totalUsage: Double
+
+ /**
+ * A flag to indicate that this slice is empty.
+ */
+ val isEmpty: Boolean
+
+ init {
+ var totalUsage = 0.0
+ var minExit = Long.MAX_VALUE
+ var maxExit = 0L
+ var nonEmpty = false
+
+ // Determine the duration of the first/last CPU to finish
+ for (i in 0 until min(model.cpus.size, slice.burst.size)) {
+ val cpu = model.cpus[i]
+ val usage = min(slice.limit[i], cpu.frequency)
+ val cpuDuration = ceil(slice.burst[i] / usage * 1000).toLong() // Convert from seconds to milliseconds
+
+ totalUsage += usage / cpu.frequency
+
+ if (cpuDuration != 0L) { // We only wait for processor cores with a non-zero burst
+ minExit = min(minExit, cpuDuration)
+ maxExit = max(maxExit, cpuDuration)
+ nonEmpty = true
+ }
+ }
+
+ this.isEmpty = !nonEmpty
+ this.totalUsage = totalUsage
+ this.minExit = minExit
+ this.maxExit = maxExit
+ }
+
+ /**
+ * Indicate that the work on the slice has started.
+ */
+ fun start() {
+ usageState.value = totalUsage / model.cpus.size
+ }
+
+ /**
+ * Flush the work performed on the slice.
+ */
+ fun stop(duration: Long): Boolean {
+ var hasFinished = true
+
+ for (i in 0 until min(model.cpus.size, slice.burst.size)) {
+ val usage = min(slice.limit[i], model.cpus[i].frequency)
+ val granted = ceil(duration / 1000.0 * usage).toLong()
+ val res = max(0, slice.burst[i] - granted)
+ slice.burst[i] = res
+
+ if (res != 0L) {
+ hasFinished = false
+ }
+ }
+
+ return hasFinished
+ }
+ }
+}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimExecutionContext.kt
index f770fa49..5801fcd5 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimExecutionContext.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,33 +20,27 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core.execution
+package org.opendc.simulator.compute
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.core.services.ServiceKey
import kotlinx.coroutines.selects.SelectClause0
import kotlinx.coroutines.selects.select
+import java.time.Clock
/**
- * Represents the execution context in which a bootable [Image] runs on a [Server].
+ * A simulated execution context in which a bootable image runs. This interface represents the
+ * firmware interface between the running image (e.g. operating system) and the physical or virtual firmware on
+ * which the image runs.
*/
-public interface ServerContext {
- /**
- * The server on which the image runs.
- */
- public val server: Server
-
+public interface SimExecutionContext {
/**
- * A list of processing units available to use.
+ * The virtual clock tracking simulation time.
*/
- public val cpus: List<ProcessingUnit>
+ public val clock: Clock
/**
- * Publish the specified [service] at the given [ServiceKey].
+ * The machine model of the machine that is running the image.
*/
- public suspend fun <T : Any> publishService(key: ServiceKey<T>, service: T)
+ public val machine: SimMachineModel
/**
* Ask the processor cores to run the specified [slice] and suspend execution until the trigger condition is met as
@@ -61,8 +53,8 @@ public interface ServerContext {
* @param slice The representation of work to run on the processors.
* @param triggerMode The trigger condition to resume execution.
*/
- public suspend fun run(slice: Slice, triggerMode: TriggerMode = TriggerMode.FIRST) =
- select<Unit> { onRun(slice, triggerMode).invoke {} }
+ public suspend fun run(slice: Slice, triggerMode: TriggerMode = TriggerMode.FIRST): Unit =
+ select { onRun(slice, triggerMode).invoke {} }
/**
* Ask the processors cores to run the specified [batch] of work slices and suspend execution until the trigger
@@ -84,7 +76,7 @@ public interface ServerContext {
batch: Sequence<Slice>,
triggerMode: TriggerMode = TriggerMode.FIRST,
merge: (Slice, Slice) -> Slice = { _, r -> r }
- ) = select<Unit> { onRun(batch, triggerMode, merge).invoke {} }
+ ): Unit = select { onRun(batch, triggerMode, merge).invoke {} }
/**
* Ask the processor cores to run the specified [slice] and select when the trigger condition is met as specified
@@ -133,7 +125,7 @@ public interface ServerContext {
* @param limit The maximum usage in terms of MHz that the processing core may use while running the burst.
* @param deadline The instant at which this slice needs to be fulfilled.
*/
- public class Slice(val burst: LongArray, val limit: DoubleArray, val deadline: Long) {
+ public class Slice(public val burst: LongArray, public val limit: DoubleArray, public val deadline: Long) {
init {
require(burst.size == limit.size) { "Incompatible array dimensions" }
}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/SimpleVirtDriver.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimHypervisor.kt
index 192db413..6087227b 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/SimpleVirtDriver.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimHypervisor.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,174 +20,100 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.virt.driver
-
-import com.atlarge.odcsim.flow.EventFlow
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.compute.core.execution.ServerManagementContext
-import com.atlarge.opendc.compute.core.execution.ShutdownException
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.core.workload.IMAGE_PERF_INTERFERENCE_MODEL
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.virt.HypervisorEvent
-import com.atlarge.opendc.core.services.ServiceKey
-import com.atlarge.opendc.core.services.ServiceRegistry
-import java.util.UUID
-import kotlin.math.ceil
-import kotlin.math.max
-import kotlin.math.min
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.FlowPreview
-import kotlinx.coroutines.InternalCoroutinesApi
-import kotlinx.coroutines.Job
+package org.opendc.simulator.compute
+
+import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.intrinsics.startCoroutineCancellable
-import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.SelectClause0
import kotlinx.coroutines.selects.SelectInstance
import kotlinx.coroutines.selects.select
+import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
+import org.opendc.simulator.compute.model.ProcessingUnit
+import org.opendc.simulator.compute.workload.SimWorkload
+import java.time.Clock
+import kotlin.math.ceil
+import kotlin.math.max
+import kotlin.math.min
/**
- * A [VirtDriver] that is backed by a simple hypervisor implementation.
+ * SimHypervisor distributes the computing requirements of multiple [SimWorkload] on a single [SimBareMetalMachine] concurrently.
+ *
+ * @param coroutineScope The [CoroutineScope] to run the simulated workloads in.
+ * @param clock The virtual clock to track the simulation time.
*/
-@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
-class SimpleVirtDriver(
- private val hostContext: ServerContext,
- scope: CoroutineScope
-) : VirtDriver, CoroutineScope by scope {
+@OptIn(ExperimentalCoroutinesApi::class, InternalCoroutinesApi::class)
+public class SimHypervisor(
+ private val coroutineScope: CoroutineScope,
+ private val clock: Clock,
+ private val listener: Listener? = null
+) : SimWorkload {
/**
- * The [Server] on which this hypervisor runs.
+ * A set for tracking the VM context objects.
*/
- val server: Server
- get() = hostContext.server
+ private val vms: MutableSet<VmExecutionContext> = mutableSetOf()
/**
- * A set for tracking the VM context objects.
+ * A flag to indicate the driver is stopped.
*/
- private val vms: MutableSet<VmServerContext> = mutableSetOf()
+ private var stopped: Boolean = false
/**
- * Current total memory use of the images on this hypervisor.
+ * The channel for scheduling new CPU requests.
*/
- private var availableMemory: Long = hostContext.server.flavor.memorySize
+ private val schedulingQueue = Channel<SchedulerCommand>(Channel.UNLIMITED)
/**
- * The [EventFlow] to emit the events.
+ * Create a [SimMachine] instance on which users may run a [SimWorkload].
+ *
+ * @param model The machine to create.
*/
- internal val eventFlow = EventFlow<HypervisorEvent>()
-
- override val events: Flow<HypervisorEvent> = eventFlow
-
- init {
- launch {
- try {
- scheduler()
- } catch (e: Exception) {
- if (e !is CancellationException) {
- simulationContext.log.error("Hypervisor scheduler failed", e)
+ public fun createMachine(model: SimMachineModel, performanceInterferenceModel: PerformanceInterferenceModel? = null): SimMachine {
+ val vm = VmSession(model, performanceInterferenceModel)
+ val vmCtx = VmExecutionContext(vm)
+
+ return object : SimMachine {
+ override val model: SimMachineModel
+ get() = vmCtx.machine
+
+ override val usage: StateFlow<Double>
+ get() = vm.usage
+
+ /**
+ * The current active workload.
+ */
+ private var activeWorkload: SimWorkload? = null
+
+ override suspend fun run(workload: SimWorkload) {
+ require(activeWorkload == null) { "Run should not be called concurrently" }
+
+ try {
+ activeWorkload = workload
+ workload.run(vmCtx)
+ } finally {
+ activeWorkload = null
}
- throw e
}
- }
- }
-
- override suspend fun spawn(
- name: String,
- image: Image,
- flavor: Flavor
- ): Server {
- val requiredMemory = flavor.memorySize
- if (availableMemory - requiredMemory < 0) {
- throw InsufficientMemoryOnServerException()
- }
- require(flavor.cpuCount <= hostContext.server.flavor.cpuCount) { "Machine does not fit" }
-
- val events = EventFlow<ServerEvent>()
- val server = Server(
- UUID.randomUUID(), name, emptyMap(), flavor, image, ServerState.BUILD,
- ServiceRegistry(), events
- )
- availableMemory -= requiredMemory
- vms.add(VmServerContext(server, events))
- vmStarted(server)
- eventFlow.emit(HypervisorEvent.VmsUpdated(this, vms.size, availableMemory))
- return server
- }
-
- internal fun cancel() {
- eventFlow.close()
- }
-
- private fun vmStarted(server: Server) {
- vms.forEach {
- val performanceModel =
- it.server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel?
- performanceModel?.vmStarted(server)
- }
- }
- private fun vmStopped(server: Server) {
- vms.forEach {
- val performanceModel =
- it.server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel?
- performanceModel?.vmStopped(server)
+ override fun toString(): String = "SimVirtualMachine"
}
}
/**
- * A scheduling command processed by the scheduler.
- */
- private sealed class SchedulerCommand {
- /**
- * Schedule the specified VM on the hypervisor.
- */
- data class Schedule(val vm: Vm) : SchedulerCommand()
-
- /**
- * De-schedule the specified VM on the hypervisor.
- */
- data class Deschedule(val vm: Vm) : SchedulerCommand()
-
- /**
- * Interrupt the scheduler.
- */
- object Interrupt : SchedulerCommand()
- }
-
- /**
- * A flag to indicate the driver is stopped.
- */
- private var stopped: Boolean = false
-
- /**
- * The channel for scheduling new CPU requests.
- */
- private val schedulingQueue = Channel<SchedulerCommand>(Channel.UNLIMITED)
-
- /**
- * The scheduling process of the hypervisor.
+ * Run the scheduling process of the hypervisor.
*/
- private suspend fun scheduler() {
- val clock = simulationContext.clock
- val maxUsage = hostContext.cpus.sumByDouble { it.frequency }
- val pCPUs = hostContext.cpus.indices.sortedBy { hostContext.cpus[it].frequency }
+ override suspend fun run(ctx: SimExecutionContext) {
+ val model = ctx.machine
+ val maxUsage = model.cpus.sumByDouble { it.frequency }
+ val pCPUs = model.cpus.indices.sortedBy { model.cpus[it].frequency }
- val vms = mutableSetOf<Vm>()
+ val vms = mutableSetOf<VmSession>()
val vcpus = mutableListOf<VCpu>()
- val usage = DoubleArray(hostContext.cpus.size)
- val burst = LongArray(hostContext.cpus.size)
+ val usage = DoubleArray(model.cpus.size)
+ val burst = LongArray(model.cpus.size)
fun process(command: SchedulerCommand) {
when (command) {
@@ -201,7 +125,8 @@ class SimpleVirtDriver(
vms -= command.vm
vcpus.removeAll(command.vm.vcpus)
}
- is SchedulerCommand.Interrupt -> {}
+ is SchedulerCommand.Interrupt -> {
+ }
}
}
@@ -223,7 +148,6 @@ class SimpleVirtDriver(
val start = clock.millis()
- val vmCount = vms.size
var duration: Double = Double.POSITIVE_INFINITY
var deadline: Long = Long.MAX_VALUE
var availableUsage = maxUsage
@@ -269,7 +193,7 @@ class SimpleVirtDriver(
// Divide the requests over the available capacity of the pCPUs fairly
for (i in pCPUs) {
- val maxCpuUsage = hostContext.cpus[i].frequency
+ val maxCpuUsage = model.cpus[i].frequency
val fraction = maxCpuUsage / maxUsage
val grantedUsage = min(maxCpuUsage, totalAllocatedUsage * fraction)
val grantedBurst = ceil(duration * grantedUsage).toLong()
@@ -284,7 +208,8 @@ class SimpleVirtDriver(
// time, so not all of the burst may be executed.
select<Boolean> {
schedulingQueue.onReceive { schedulingQueue.offer(it); true }
- hostContext.onRun(ServerContext.Slice(burst, usage, deadline), ServerContext.TriggerMode.DEADLINE).invoke { false }
+ ctx.onRun(SimExecutionContext.Slice(burst, usage, deadline), SimExecutionContext.TriggerMode.DEADLINE)
+ .invoke { false }
}
val end = clock.millis()
@@ -295,7 +220,8 @@ class SimpleVirtDriver(
}
// The total requested burst that the VMs wanted to run in the time-frame that we ran.
- val totalRequestedSubBurst = vcpus.map { ceil((duration * 1000) / (it.vm.deadline - start) * it.burst).toLong() }.sum()
+ val totalRequestedSubBurst =
+ vcpus.map { ceil((duration * 1000) / (it.vm.deadline - start) * it.burst).toLong() }.sum()
val totalRemainder = burst.sum()
val totalGrantedBurst = totalAllocatedBurst - totalRemainder
@@ -309,9 +235,7 @@ class SimpleVirtDriver(
val vm = vmIterator.next()
// Apply performance interference model
- val performanceModel =
- vm.ctx.server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel?
- val performanceScore = performanceModel?.apply(serverLoad) ?: 1.0
+ val performanceScore = vm.performanceInterferenceModel?.apply(serverLoad) ?: 1.0
var hasFinished = false
for (vcpu in vm.vcpus) {
@@ -329,7 +253,7 @@ class SimpleVirtDriver(
// Compute remaining burst time to be executed for the request
if (vcpu.consume(usedBurst)) {
hasFinished = true
- } else if (vm.deadline <= end && hostContext.server.state != ServerState.ERROR) {
+ } else if (vm.deadline <= end) {
// Request must have its entire burst consumed or otherwise we have overcommission
// Note that we count the overcommissioned burst if the hypervisor has failed.
totalOvercommissionedBurst += vcpu.burst
@@ -345,23 +269,60 @@ class SimpleVirtDriver(
}
}
- eventFlow.emit(
- HypervisorEvent.SliceFinished(
- this@SimpleVirtDriver,
- totalRequestedBurst,
- min(totalRequestedSubBurst, totalGrantedBurst), // We can run more than requested due to timing
- totalOvercommissionedBurst,
- totalInterferedBurst, // Might be smaller than zero due to FP rounding errors,
- min(totalAllocatedUsage, totalRequestedUsage), // The allocated usage might be slightly higher due to FP rounding
- totalRequestedUsage,
- vmCount, // Some VMs might already have finished, so keep initial VM count
- server
- )
+ listener?.onSliceFinish(
+ this,
+ totalRequestedBurst,
+ min(totalRequestedSubBurst, totalGrantedBurst), // We can run more than requested due to timing
+ totalOvercommissionedBurst,
+ totalInterferedBurst, // Might be smaller than zero due to FP rounding errors,
+ min(
+ totalAllocatedUsage,
+ totalRequestedUsage
+ ), // The allocated usage might be slightly higher due to FP rounding
+ totalRequestedUsage
)
}
}
/**
+ * Event listener for hypervisor events.
+ */
+ public interface Listener {
+ /**
+ * This method is invoked when a slice is finished.
+ */
+ public fun onSliceFinish(
+ hypervisor: SimHypervisor,
+ requestedBurst: Long,
+ grantedBurst: Long,
+ overcommissionedBurst: Long,
+ interferedBurst: Long,
+ cpuUsage: Double,
+ cpuDemand: Double
+ )
+ }
+
+ /**
+ * A scheduling command processed by the scheduler.
+ */
+ private sealed class SchedulerCommand {
+ /**
+ * Schedule the specified VM on the hypervisor.
+ */
+ data class Schedule(val vm: VmSession) : SchedulerCommand()
+
+ /**
+ * De-schedule the specified VM on the hypervisor.
+ */
+ data class Deschedule(val vm: VmSession) : SchedulerCommand()
+
+ /**
+ * Interrupt the scheduler.
+ */
+ object Interrupt : SchedulerCommand()
+ }
+
+ /**
* A virtual machine running on the hypervisor.
*
* @param ctx The execution context the vCPU runs in.
@@ -370,10 +331,11 @@ class SimpleVirtDriver(
* @param select The function to select on finish.
*/
@OptIn(InternalCoroutinesApi::class)
- private data class Vm(
- val ctx: VmServerContext,
- var triggerMode: ServerContext.TriggerMode = ServerContext.TriggerMode.FIRST,
- var merge: (ServerContext.Slice, ServerContext.Slice) -> ServerContext.Slice = { _, r -> r },
+ private data class VmSession(
+ val model: SimMachineModel,
+ val performanceInterferenceModel: PerformanceInterferenceModel? = null,
+ var triggerMode: SimExecutionContext.TriggerMode = SimExecutionContext.TriggerMode.FIRST,
+ var merge: (SimExecutionContext.Slice, SimExecutionContext.Slice) -> SimExecutionContext.Slice = { _, r -> r },
var select: () -> Unit = {}
) {
/**
@@ -384,12 +346,12 @@ class SimpleVirtDriver(
/**
* The slices that the VM wants to run.
*/
- var queue: Iterator<ServerContext.Slice> = emptyList<ServerContext.Slice>().iterator()
+ var queue: Iterator<SimExecutionContext.Slice> = emptyList<SimExecutionContext.Slice>().iterator()
/**
* The current active slice.
*/
- var activeSlice: ServerContext.Slice? = null
+ var activeSlice: SimExecutionContext.Slice? = null
/**
* The current deadline of the VM.
@@ -403,19 +365,24 @@ class SimpleVirtDriver(
val isIdle: Boolean
get() = activeSlice == null
+ /**
+ * The usage of the virtual machine.
+ */
+ val usage: MutableStateFlow<Double> = MutableStateFlow(0.0)
+
init {
- vcpus = ctx.cpus.mapIndexed { i, model -> VCpu(this, model, i) }
+ vcpus = model.cpus.mapIndexed { i, model -> VCpu(this, model, i) }
}
/**
* Schedule the given slices on this vCPU, replacing the existing slices.
*/
- fun schedule(slices: Sequence<ServerContext.Slice>) {
+ fun schedule(slices: Sequence<SimExecutionContext.Slice>) {
queue = slices.iterator()
if (queue.hasNext()) {
activeSlice = queue.next()
- vcpus.forEach { it.refresh() }
+ refresh()
}
}
@@ -423,9 +390,9 @@ class SimpleVirtDriver(
* Cancel the existing workload on the VM.
*/
fun cancel() {
- queue = emptyList<ServerContext.Slice>().iterator()
+ queue = emptyList<SimExecutionContext.Slice>().iterator()
activeSlice = null
- vcpus.forEach { it.refresh() }
+ refresh()
}
/**
@@ -444,7 +411,7 @@ class SimpleVirtDriver(
this.activeSlice = slice
// Update the vCPU cache
- vcpus.forEach { it.refresh() }
+ refresh()
false
} else {
@@ -453,6 +420,14 @@ class SimpleVirtDriver(
true
}
}
+
+ /**
+ * Refresh the vCPU cache.
+ */
+ fun refresh() {
+ vcpus.forEach { it.refresh() }
+ usage.value = vcpus.sumByDouble { it.burst / it.limit } / vcpus.size
+ }
}
/**
@@ -463,7 +438,7 @@ class SimpleVirtDriver(
* @param id The id of the vCPU with respect to the VM.
*/
private data class VCpu(
- val vm: Vm,
+ val vm: VmSession,
val model: ProcessingUnit,
val id: Int
) : Comparable<VCpu> {
@@ -506,119 +481,54 @@ class SimpleVirtDriver(
* Compare to another vCPU based on the current load of the vCPU.
*/
override fun compareTo(other: VCpu): Int {
- var cmp = limit.compareTo(other.limit)
-
- if (cmp != 0) {
- return cmp
- }
-
- cmp = vm.ctx.server.uid.compareTo(other.vm.ctx.server.uid)
-
- if (cmp != 0) {
- return cmp
- }
-
- return id.compareTo(other.id)
+ return limit.compareTo(other.limit)
}
/**
* Create a string representation of the vCPU.
*/
override fun toString(): String =
- "vCPU(vm=${vm.ctx.server.uid},id=$id,burst=$burst,limit=$limit,allocatedLimit=$allocatedLimit)"
+ "vCPU(id=$id,burst=$burst,limit=$limit,allocatedLimit=$allocatedLimit)"
}
/**
* The execution context in which a VM runs.
*
- * @param server The details of the VM.
- * @param events The event stream to publish to.
*/
- private inner class VmServerContext(server: Server, val events: EventFlow<ServerEvent>) : ServerManagementContext, DisposableHandle {
- private var finalized: Boolean = false
- private var initialized: Boolean = false
- private val vm: Vm
-
- internal val job: Job = launch {
- delay(1) // TODO Introduce boot time
- init()
- try {
- server.image(this@VmServerContext)
- exit()
- } catch (cause: Throwable) {
- exit(cause)
- }
- }
+ private inner class VmExecutionContext(val session: VmSession) :
+ SimExecutionContext, DisposableHandle {
+ override val machine: SimMachineModel
+ get() = session.model
- override var server: Server = server
- set(value) {
- if (field.state != value.state) {
- events.emit(ServerEvent.StateChanged(value, field.state))
- }
-
- field = value
- }
-
- override val cpus: List<ProcessingUnit> = hostContext.cpus.take(server.flavor.cpuCount)
-
- init {
- vm = Vm(this)
- }
-
- override suspend fun <T : Any> publishService(key: ServiceKey<T>, service: T) {
- server = server.copy(services = server.services.put(key, service))
- events.emit(ServerEvent.ServicePublished(server, key))
- }
-
- override suspend fun init() {
- assert(!finalized) { "VM is already finalized" }
-
- server = server.copy(state = ServerState.ACTIVE)
- initialized = true
- }
-
- override suspend fun exit(cause: Throwable?) {
- finalized = true
-
- val serverState =
- if (cause == null || (cause is ShutdownException && cause.cause == null))
- ServerState.SHUTOFF
- else
- ServerState.ERROR
- server = server.copy(state = serverState)
- availableMemory += server.flavor.memorySize
- vms.remove(this)
- vmStopped(server)
- eventFlow.emit(HypervisorEvent.VmsUpdated(this@SimpleVirtDriver, vms.size, availableMemory))
- events.close()
- }
+ override val clock: Clock
+ get() = this@SimHypervisor.clock
@OptIn(InternalCoroutinesApi::class)
override fun onRun(
- batch: Sequence<ServerContext.Slice>,
- triggerMode: ServerContext.TriggerMode,
- merge: (ServerContext.Slice, ServerContext.Slice) -> ServerContext.Slice
+ batch: Sequence<SimExecutionContext.Slice>,
+ triggerMode: SimExecutionContext.TriggerMode,
+ merge: (SimExecutionContext.Slice, SimExecutionContext.Slice) -> SimExecutionContext.Slice
): SelectClause0 = object : SelectClause0 {
@InternalCoroutinesApi
override fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R) {
- vm.triggerMode = triggerMode
- vm.merge = merge
- vm.select = {
+ session.triggerMode = triggerMode
+ session.merge = merge
+ session.select = {
if (select.trySelect()) {
block.startCoroutineCancellable(select.completion)
}
}
- vm.schedule(batch)
+ session.schedule(batch)
// Indicate to the hypervisor that the VM should be re-scheduled
- schedulingQueue.offer(SchedulerCommand.Schedule(vm))
- select.disposeOnSelect(this@VmServerContext)
+ schedulingQueue.offer(SchedulerCommand.Schedule(session))
+ select.disposeOnSelect(this@VmExecutionContext)
}
}
override fun dispose() {
- if (!vm.isIdle) {
- vm.cancel()
- schedulingQueue.offer(SchedulerCommand.Deschedule(vm))
+ if (!session.isIdle) {
+ session.cancel()
+ schedulingQueue.offer(SchedulerCommand.Deschedule(session))
}
}
}
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt
new file mode 100644
index 00000000..f66085af
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.StateFlow
+import org.opendc.simulator.compute.workload.SimWorkload
+
+/**
+ * A generic machine that is able to run a [SimWorkload].
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+public interface SimMachine {
+ /**
+ * The model of the machine containing its specifications.
+ */
+ public val model: SimMachineModel
+
+ /**
+ * A [StateFlow] representing the CPU usage of the simulated machine.
+ */
+ public val usage: StateFlow<Double>
+
+ /**
+ * Run the specified [SimWorkload] on this machine and suspend execution util the workload has finished.
+ */
+ public suspend fun run(workload: SimWorkload)
+}
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineModel.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineModel.kt
new file mode 100644
index 00000000..c2988b11
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineModel.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute
+
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingUnit
+
+/**
+ * A description of the physical or virtual machine on which a bootable image runs.
+ *
+ * @property cpus The list of processing units available to the image.
+ * @property memory The list of memory units available to the image.
+ */
+public data class SimMachineModel(public val cpus: List<ProcessingUnit>, public val memory: List<MemoryUnit>)
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/interference/PerformanceInterferenceModel.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/interference/PerformanceInterferenceModel.kt
new file mode 100644
index 00000000..4c409887
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/interference/PerformanceInterferenceModel.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute.interference
+
+import java.util.*
+import kotlin.random.Random
+
+/**
+ * Meta-data key for the [PerformanceInterferenceModel] of an image.
+ */
+public const val IMAGE_PERF_INTERFERENCE_MODEL: String = "image:performance-interference"
+
+/**
+ * Performance Interference Model describing the variability incurred by different sets of workloads if colocated.
+ *
+ * @param items The [PerformanceInterferenceModel.Item]s that make up this model.
+ */
+public class PerformanceInterferenceModel(
+ public val items: SortedSet<Item>,
+ private val random: Random = Random(0)
+) {
+ private var intersectingItems: List<Item> = emptyList()
+ private val colocatedWorkloads = TreeMap<String, Int>()
+
+ /**
+ * Indicate that a VM has started.
+ */
+ public fun onStart(name: String) {
+ colocatedWorkloads.merge(name, 1, Int::plus)
+ intersectingItems = items.filter { item -> doesMatch(item) }
+ }
+
+ /**
+ * Indicate that a VM has stopped.
+ */
+ public fun onStop(name: String) {
+ colocatedWorkloads.computeIfPresent(name) { _, v -> (v - 1).takeUnless { it == 0 } }
+ intersectingItems = items.filter { item -> doesMatch(item) }
+ }
+
+ /**
+ * Compute the performance interference based on the current server load.
+ */
+ public fun apply(currentServerLoad: Double): Double {
+ if (intersectingItems.isEmpty()) {
+ return 1.0
+ }
+ val score = intersectingItems
+ .firstOrNull { it.minServerLoad <= currentServerLoad }
+
+ // Apply performance penalty to (on average) only one of the VMs
+ return if (score != null && random.nextInt(score.workloadNames.size) == 0) {
+ score.performanceScore
+ } else {
+ 1.0
+ }
+ }
+
+ private fun doesMatch(item: Item): Boolean {
+ var count = 0
+ for (
+ name in item.workloadNames.subSet(
+ colocatedWorkloads.firstKey(),
+ colocatedWorkloads.lastKey() + "\u0000"
+ )
+ ) {
+ count += colocatedWorkloads.getOrDefault(name, 0)
+ if (count > 1)
+ return true
+ }
+ return false
+ }
+
+ /**
+ * Model describing how a specific set of workloads causes performance variability for each workload.
+ *
+ * @param workloadNames The names of the workloads that together cause performance variability for each workload in the set.
+ * @param minServerLoad The minimum total server load at which this interference is activated and noticeable.
+ * @param performanceScore The performance score that should be applied to each workload's performance. 1 means no
+ * influence, <1 means that performance degrades, and >1 means that performance improves.
+ */
+ public data class Item(
+ public val workloadNames: SortedSet<String>,
+ public val minServerLoad: Double,
+ public val performanceScore: Double
+ ) : Comparable<Item> {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as Item
+
+ if (workloadNames != other.workloadNames) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int = workloadNames.hashCode()
+
+ override fun compareTo(other: Item): Int {
+ var cmp = performanceScore.compareTo(other.performanceScore)
+ if (cmp != 0) {
+ return cmp
+ }
+
+ cmp = minServerLoad.compareTo(other.minServerLoad)
+ if (cmp != 0) {
+ return cmp
+ }
+
+ return hashCode().compareTo(other.hashCode())
+ }
+ }
+}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/MemoryUnit.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MemoryUnit.kt
index ce57fc72..bcbde5b1 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/MemoryUnit.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MemoryUnit.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core
+package org.opendc.simulator.compute.model
/**
* A memory unit of a compute resource, either virtual or physical.
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingNode.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/ProcessingNode.kt
index 91f5dde9..58ed816c 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingNode.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/ProcessingNode.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core
+package org.opendc.simulator.compute.model
/**
* A processing node/package/socket containing possibly several CPU cores.
@@ -32,9 +30,9 @@ package com.atlarge.opendc.compute.core
* @property arch The micro-architecture of the processor node.
* @property coreCount The number of logical CPUs in the processor node.
*/
-data class ProcessingNode(
- val vendor: String,
- val arch: String,
- val modelName: String,
- val coreCount: Int
+public data class ProcessingNode(
+ public val vendor: String,
+ public val arch: String,
+ public val modelName: String,
+ public val coreCount: Int
)
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/ProcessingUnit.kt
index ba148ee0..415e95e6 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/ProcessingUnit.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core
+package org.opendc.simulator.compute.model
/**
* A single logical compute unit of processor node, either virtual or physical.
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkload.kt
index d65e7e94..918a78bd 100644
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkload.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,32 +20,24 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core.image
+package org.opendc.simulator.compute.workload
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.TagContainer
-import java.util.UUID
+import org.opendc.simulator.compute.SimExecutionContext
import kotlin.math.min
/**
- * An application [Image] that models applications performing a static number of floating point operations ([flops]) on
+ * A [SimWorkload] that models applications performing a static number of floating point operations ([flops]) on
* a compute resource.
*
- * @property uid The unique identifier of this image.
- * @property name The name of this image.
- * @property tags The tags attached to the image.
* @property flops The number of floating point operations to perform for this task in MFLOPs.
* @property cores The number of cores that the image is able to utilize.
* @property utilization A model of the CPU utilization of the application.
*/
-data class FlopsApplicationImage(
- public override val uid: UUID,
- public override val name: String,
- public override val tags: TagContainer,
+public class SimFlopsWorkload(
public val flops: Long,
public val cores: Int,
public val utilization: Double = 0.8
-) : Image {
+) : SimWorkload {
init {
require(flops >= 0) { "Negative number of flops" }
require(cores > 0) { "Negative number of cores or no cores" }
@@ -57,11 +47,11 @@ data class FlopsApplicationImage(
/**
* Execute the runtime behavior based on a number of floating point operations to execute.
*/
- override suspend fun invoke(ctx: ServerContext) {
- val cores = min(this.cores, ctx.server.flavor.cpuCount)
+ override suspend fun run(ctx: SimExecutionContext) {
+ val cores = min(this.cores, ctx.machine.cpus.size)
val burst = LongArray(cores) { flops / cores }
- val maxUsage = DoubleArray(cores) { i -> ctx.cpus[i].frequency * utilization }
+ val maxUsage = DoubleArray(cores) { i -> ctx.machine.cpus[i].frequency * utilization }
- ctx.run(ServerContext.Slice(burst, maxUsage, Long.MAX_VALUE), triggerMode = ServerContext.TriggerMode.LAST)
+ ctx.run(SimExecutionContext.Slice(burst, maxUsage, Long.MAX_VALUE), triggerMode = SimExecutionContext.TriggerMode.LAST)
}
}
diff --git a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationContext.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt
index c51d1d8b..7b1ddf32 100644
--- a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/SimulationContext.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2018 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,42 +20,34 @@
* SOFTWARE.
*/
-package com.atlarge.odcsim
+package org.opendc.simulator.compute.workload
-import java.time.Clock
-import kotlin.coroutines.CoroutineContext
-import kotlin.coroutines.coroutineContext
-import org.slf4j.Logger
+import org.opendc.simulator.compute.SimExecutionContext
+import kotlin.math.min
/**
- * Represents the execution context of a simulation domain.
+ * A [SimWorkload] that replays a workload trace consisting of multiple fragments, each indicating the resource
+ * consumption for some period of time.
*/
-public interface SimulationContext : CoroutineContext.Element {
- /**
- * Key for [SimulationContext] instance in the coroutine context.
- */
- companion object Key : CoroutineContext.Key<SimulationContext>
+public class SimTraceWorkload(public val trace: Sequence<Fragment>) : SimWorkload {
+ override suspend fun run(ctx: SimExecutionContext) {
+ var offset = ctx.clock.millis()
- /**
- * The reference to the current simulation domain.
- */
- public val domain: Domain
+ val batch = trace.map { fragment ->
+ val cores = min(fragment.cores, ctx.machine.cpus.size)
+ val burst = LongArray(cores) { fragment.flops / cores }
+ val usage = DoubleArray(cores) { fragment.usage / cores }
+ offset += fragment.duration
+ SimExecutionContext.Slice(burst, usage, offset)
+ }
- /**
- * The clock tracking the simulation time.
- */
- public val clock: Clock
+ ctx.run(batch)
+ }
+
+ override fun toString(): String = "SimTraceWorkload"
/**
- * A logger instance tied to the logical process.
+ * A fragment of the workload.
*/
- public val log: Logger
+ public data class Fragment(val time: Long, val flops: Long, val duration: Long, val usage: Double, val cores: Int)
}
-
-/**
- * The simulation context of the current coroutine.
- */
-@Suppress("WRONG_MODIFIER_TARGET")
-public suspend inline val simulationContext: SimulationContext
- @Suppress("ILLEGAL_SUSPEND_PROPERTY_ACCESS")
- get() = coroutineContext[SimulationContext] ?: throw IllegalStateException("No simulation context available")
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimWorkload.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimWorkload.kt
new file mode 100644
index 00000000..2add8cce
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimWorkload.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute.workload
+
+import org.opendc.simulator.compute.SimExecutionContext
+
+/**
+ * A model that characterizes the runtime behavior of some particular workload.
+ *
+ * Workloads are stateful objects that may be paused and resumed at a later moment. As such, be careful when using the
+ * same [SimWorkload] from multiple contexts as only a single concurrent [run] call is expected.
+ */
+public interface SimWorkload {
+ /**
+ * Launch the workload in the specified [SimExecutionContext].
+ *
+ * This method should encapsulate and characterize the runtime behavior of the instance resulting from launching
+ * the workload on some machine, in terms of the resource consumption on the machine.
+ */
+ public suspend fun run(ctx: SimExecutionContext)
+}
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimHypervisorTest.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimHypervisorTest.kt
new file mode 100644
index 00000000..78bd2940
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimHypervisorTest.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.yield
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertAll
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
+import org.opendc.simulator.compute.workload.SimTraceWorkload
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import java.time.Clock
+
+/**
+ * Test suite for the [SimHypervisor] class.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+internal class SimHypervisorTest {
+ private lateinit var scope: TestCoroutineScope
+ private lateinit var clock: Clock
+ private lateinit var machineModel: SimMachineModel
+
+ @BeforeEach
+ fun setUp() {
+ scope = TestCoroutineScope()
+ clock = DelayControllerClockAdapter(scope)
+
+ val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
+ machineModel = SimMachineModel(
+ cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
+ memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ )
+ }
+
+ /**
+ * Test overcommissioning of a hypervisor.
+ */
+ @Test
+ fun overcommission() {
+ val listener = object : SimHypervisor.Listener {
+ var totalRequestedBurst = 0L
+ var totalGrantedBurst = 0L
+ var totalOvercommissionedBurst = 0L
+
+ override fun onSliceFinish(
+ hypervisor: SimHypervisor,
+ requestedBurst: Long,
+ grantedBurst: Long,
+ overcommissionedBurst: Long,
+ interferedBurst: Long,
+ cpuUsage: Double,
+ cpuDemand: Double
+ ) {
+ totalRequestedBurst += requestedBurst
+ totalGrantedBurst += grantedBurst
+ totalOvercommissionedBurst += overcommissionedBurst
+ }
+ }
+
+ scope.launch {
+ val duration = 5 * 60L
+ val workloadA =
+ SimTraceWorkload(
+ sequenceOf(
+ SimTraceWorkload.Fragment(0, 28L * duration, duration * 1000, 28.0, 2),
+ SimTraceWorkload.Fragment(0, 3500L * duration, duration * 1000, 3500.0, 2),
+ SimTraceWorkload.Fragment(0, 0, duration * 1000, 0.0, 2),
+ SimTraceWorkload.Fragment(0, 183L * duration, duration * 1000, 183.0, 2)
+ ),
+ )
+ val workloadB =
+ SimTraceWorkload(
+ sequenceOf(
+ SimTraceWorkload.Fragment(0, 28L * duration, duration * 1000, 28.0, 2),
+ SimTraceWorkload.Fragment(0, 3100L * duration, duration * 1000, 3100.0, 2),
+ SimTraceWorkload.Fragment(0, 0, duration * 1000, 0.0, 2),
+ SimTraceWorkload.Fragment(0, 73L * duration, duration * 1000, 73.0, 2)
+ )
+ )
+
+ val machine = SimBareMetalMachine(scope, clock, machineModel)
+ val hypervisor = SimHypervisor(scope, clock, listener)
+
+ launch {
+ machine.run(hypervisor)
+ }
+
+ yield()
+ launch { hypervisor.createMachine(machineModel).run(workloadA) }
+ launch { hypervisor.createMachine(machineModel).run(workloadB) }
+ }
+
+ scope.advanceUntilIdle()
+
+ assertAll(
+ { Assertions.assertEquals(emptyList<Throwable>(), scope.uncaughtExceptions, "No errors") },
+ { Assertions.assertEquals(2073600, listener.totalRequestedBurst, "Requested Burst does not match") },
+ { Assertions.assertEquals(2013600, listener.totalGrantedBurst, "Granted Burst does not match") },
+ { Assertions.assertEquals(60000, listener.totalOvercommissionedBurst, "Overcommissioned Burst does not match") },
+ { Assertions.assertEquals(1200001, scope.currentTime) }
+ )
+ }
+}
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
new file mode 100644
index 00000000..332ca8e9
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.simulator.compute.model.MemoryUnit
+import org.opendc.simulator.compute.model.ProcessingNode
+import org.opendc.simulator.compute.model.ProcessingUnit
+import org.opendc.simulator.compute.workload.SimFlopsWorkload
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+
+/**
+ * Test suite for the [SimBareMetalMachine] class.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+class SimMachineTest {
+ private lateinit var machineModel: SimMachineModel
+
+ @BeforeEach
+ fun setUp() {
+ val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
+
+ machineModel = SimMachineModel(
+ cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
+ memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ )
+ }
+
+ @Test
+ fun testFlopsWorkload() {
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
+ val machine = SimBareMetalMachine(testScope, clock, machineModel)
+
+ testScope.runBlockingTest {
+ machine.run(SimFlopsWorkload(2_000, 2, utilization = 1.0))
+
+ // Two cores execute 1000 MFlOps per second (1000 ms)
+ assertEquals(1000, testScope.currentTime)
+ }
+ }
+
+ @Test
+ fun testUsage() {
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
+ val machine = SimBareMetalMachine(testScope, clock, machineModel)
+
+ testScope.runBlockingTest {
+ machine.run(SimFlopsWorkload(2_000, 2, utilization = 1.0))
+ assertEquals(1.0, machine.usage.value)
+
+ // Wait for the usage to reset
+ delay(1)
+ assertEquals(0.0, machine.usage.value)
+ }
+ }
+}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImageTest.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt
index 1c7b751c..51bed76c 100644
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImageTest.kt
+++ b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,57 +20,54 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.compute.core.image
+package org.opendc.simulator.compute.workload
-import java.util.UUID
-import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
/**
- * Test suite for [FlopsApplicationImage]
+ * Test suite for [SimFlopsWorkload] class.
*/
-@DisplayName("FlopsApplicationImage")
-internal class FlopsApplicationImageTest {
+class SimFlopsWorkloadTest {
@Test
- fun `flops must be non-negative`() {
+ fun testFlopsNonNegative() {
assertThrows<IllegalArgumentException>("FLOPs must be non-negative") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), -1, 1)
+ SimFlopsWorkload(-1, 1)
}
}
@Test
- fun `cores cannot be zero`() {
+ fun testCoresNonZero() {
assertThrows<IllegalArgumentException>("Cores cannot be zero") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 0)
+ SimFlopsWorkload(1, 0)
}
}
@Test
- fun `cores cannot be negative`() {
+ fun testCoresPositive() {
assertThrows<IllegalArgumentException>("Cores cannot be negative") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, -1)
+ SimFlopsWorkload(1, -1)
}
}
@Test
- fun `utilization cannot be zero`() {
+ fun testUtilizationNonZero() {
assertThrows<IllegalArgumentException>("Utilization cannot be zero") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 1, 0.0)
+ SimFlopsWorkload(1, 1, 0.0)
}
}
@Test
- fun `utilization cannot be negative`() {
+ fun testUtilizationPositive() {
assertThrows<IllegalArgumentException>("Utilization cannot be negative") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 1, -1.0)
+ SimFlopsWorkload(1, 1, -1.0)
}
}
@Test
- fun `utilization cannot be larger than one`() {
+ fun testUtilizationNotLargerThanOne() {
assertThrows<IllegalArgumentException>("Utilization cannot be larger than one") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 1, 2.0)
+ SimFlopsWorkload(1, 1, 2.0)
}
}
}
diff --git a/simulator/opendc-simulator/opendc-simulator-core/build.gradle.kts b/simulator/opendc-simulator/opendc-simulator-core/build.gradle.kts
new file mode 100644
index 00000000..a740dcf3
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-core/build.gradle.kts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+description = "Simulation-specific code for use in OpenDC"
+
+/* Build configuration */
+plugins {
+ `kotlin-library-convention`
+}
+
+dependencies {
+ api("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Library.KOTLINX_COROUTINES}")
+}
diff --git a/simulator/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/utils/DelayControllerClockAdapter.kt b/simulator/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/utils/DelayControllerClockAdapter.kt
new file mode 100644
index 00000000..84c18e87
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/utils/DelayControllerClockAdapter.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.utils
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.DelayController
+import java.time.Clock
+import java.time.Instant
+import java.time.ZoneId
+
+/**
+ * A virtual [Clock] that abstracts accesses to [DelayController]'s virtual clock.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+public class DelayControllerClockAdapter(
+ private val delayController: DelayController,
+ private val zone: ZoneId = ZoneId.systemDefault()
+) : Clock() {
+ override fun getZone(): ZoneId = zone
+
+ override fun withZone(zone: ZoneId): Clock = DelayControllerClockAdapter(delayController, zone)
+
+ override fun instant(): Instant = Instant.ofEpochMilli(millis())
+
+ override fun millis(): Long = delayController.currentTime
+}
diff --git a/simulator/opendc-simulator/opendc-simulator-failures/build.gradle.kts b/simulator/opendc-simulator/opendc-simulator-failures/build.gradle.kts
new file mode 100644
index 00000000..1c30506f
--- /dev/null
+++ b/simulator/opendc-simulator/opendc-simulator-failures/build.gradle.kts
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+description = "Failure models for OpenDC"
+
+plugins {
+ `kotlin-library-convention`
+}
+
+dependencies {
+ api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Library.KOTLINX_COROUTINES}")
+}
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/CorrelatedFaultInjector.kt b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/CorrelatedFaultInjector.kt
index f77a581e..0e15f338 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/CorrelatedFaultInjector.kt
+++ b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/CorrelatedFaultInjector.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,25 +20,22 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.failure
+package org.opendc.simulator.failures
-import com.atlarge.odcsim.Domain
-import com.atlarge.odcsim.simulationContext
+import kotlinx.coroutines.*
+import java.time.Clock
import kotlin.math.exp
import kotlin.math.max
import kotlin.random.Random
import kotlin.random.asJavaRandom
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.ensureActive
-import kotlinx.coroutines.launch
/**
* A [FaultInjector] that injects fault in the system which are correlated to each other. Failures do not occur in
* isolation, but will trigger other faults.
*/
public class CorrelatedFaultInjector(
- private val domain: Domain,
+ private val coroutineScope: CoroutineScope,
+ private val clock: Clock,
private val iatScale: Double,
private val iatShape: Double,
private val sizeScale: Double,
@@ -72,7 +67,7 @@ public class CorrelatedFaultInjector(
// Clean up the domain if it finishes
domain.scope.coroutineContext[Job]!!.invokeOnCompletion {
- this@CorrelatedFaultInjector.domain.launch {
+ this@CorrelatedFaultInjector.coroutineScope.launch {
active -= domain
if (active.isEmpty()) {
@@ -86,7 +81,7 @@ public class CorrelatedFaultInjector(
return
}
- job = this.domain.launch {
+ job = this.coroutineScope.launch {
while (active.isNotEmpty()) {
ensureActive()
@@ -94,7 +89,7 @@ public class CorrelatedFaultInjector(
val d = lognvariate(iatScale, iatShape) * 3.6e6
// Handle long overflow
- if (simulationContext.clock.millis() + d <= 0) {
+ if (clock.millis() + d <= 0) {
return@launch
}
@@ -111,7 +106,7 @@ public class CorrelatedFaultInjector(
val df = max(lognvariate(dScale, dShape) * 6e4, 15 * 6e4)
// Handle long overflow
- if (simulationContext.clock.millis() + df <= 0) {
+ if (clock.millis() + df <= 0) {
return@launch
}
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FailureDomain.kt b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/FailureDomain.kt
index d56df3c9..dc3006e8 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FailureDomain.kt
+++ b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/FailureDomain.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.failure
+package org.opendc.simulator.failures
import kotlinx.coroutines.CoroutineScope
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FaultInjector.kt b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/FaultInjector.kt
index ac7a08de..a866260c 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FaultInjector.kt
+++ b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/FaultInjector.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.failure
+package org.opendc.simulator.failures
/**
* An interface for stochastically injecting faults into a running system.
diff --git a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/UncorrelatedFaultInjector.kt b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/UncorrelatedFaultInjector.kt
index 0f62667f..b3bd737e 100644
--- a/simulator/opendc/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/UncorrelatedFaultInjector.kt
+++ b/simulator/opendc-simulator/opendc-simulator-failures/src/main/kotlin/org/opendc/simulator/failures/UncorrelatedFaultInjector.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +20,25 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.core.failure
+package org.opendc.simulator.failures
-import com.atlarge.odcsim.simulationContext
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import java.time.Clock
import kotlin.math.ln1p
import kotlin.math.pow
import kotlin.random.Random
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
/**
* A [FaultInjector] that injects uncorrelated faults into the system, meaning that failures of the subsystems are
* independent.
*/
-public class UncorrelatedFaultInjector(private val alpha: Double, private val beta: Double, private val random: Random = Random(0)) : FaultInjector {
+public class UncorrelatedFaultInjector(
+ private val clock: Clock,
+ private val alpha: Double,
+ private val beta: Double,
+ private val random: Random = Random(0)
+) : FaultInjector {
/**
* Enqueue the specified [FailureDomain] to fail some time in the future.
*/
@@ -44,7 +47,7 @@ public class UncorrelatedFaultInjector(private val alpha: Double, private val be
val d = random.weibull(alpha, beta) * 1e3 // Make sure to convert delay to milliseconds
// Handle long overflow
- if (simulationContext.clock.millis() + d <= 0) {
+ if (clock.millis() + d <= 0) {
return@launch
}
diff --git a/simulator/opendc-utils/build.gradle.kts b/simulator/opendc-utils/build.gradle.kts
new file mode 100644
index 00000000..d66148c4
--- /dev/null
+++ b/simulator/opendc-utils/build.gradle.kts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+description = "Utilities used across OpenDC modules"
+
+/* Build configuration */
+plugins {
+ `kotlin-library-convention`
+}
+
+dependencies {
+ api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Library.KOTLINX_COROUTINES}")
+}
diff --git a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/flow/EventFlow.kt b/simulator/opendc-utils/src/main/kotlin/org/opendc/utils/flow/EventFlow.kt
index 0e18f82f..948595b1 100644
--- a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/flow/EventFlow.kt
+++ b/simulator/opendc-utils/src/main/kotlin/org/opendc/utils/flow/EventFlow.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +20,8 @@
* SOFTWARE.
*/
-package com.atlarge.odcsim.flow
+package org.opendc.utils.flow
-import java.util.WeakHashMap
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.InternalCoroutinesApi
@@ -61,7 +58,7 @@ public fun <T> EventFlow(): EventFlow<T> = EventFlowImpl()
@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
private class EventFlowImpl<T> : EventFlow<T> {
private var closed: Boolean = false
- private val subscribers = WeakHashMap<SendChannel<T>, Unit>()
+ private val subscribers = HashMap<SendChannel<T>, Unit>()
override fun emit(event: T) {
synchronized(this) {
diff --git a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/flow/StateFlow.kt b/simulator/opendc-utils/src/main/kotlin/org/opendc/utils/flow/StateFlow.kt
index 50add0ad..996e7700 100644
--- a/simulator/odcsim/odcsim-api/src/main/kotlin/com/atlarge/odcsim/flow/StateFlow.kt
+++ b/simulator/opendc-utils/src/main/kotlin/org/opendc/utils/flow/StateFlow.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +20,7 @@
* SOFTWARE.
*/
-package com.atlarge.odcsim.flow
+package org.opendc.utils.flow
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
diff --git a/simulator/opendc/opendc-workflows/build.gradle.kts b/simulator/opendc-workflows/build.gradle.kts
index 7a5e2067..f61bdac6 100644
--- a/simulator/opendc/opendc-workflows/build.gradle.kts
+++ b/simulator/opendc-workflows/build.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2019 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,12 +28,16 @@ plugins {
}
dependencies {
- api(project(":opendc:opendc-core"))
- api(project(":opendc:opendc-compute"))
- implementation(kotlin("stdlib"))
+ api(project(":opendc-core"))
+ api(project(":opendc-compute:opendc-compute-core"))
+ implementation(project(":opendc-utils"))
- testRuntimeOnly(project(":odcsim:odcsim-engine-omega"))
- testImplementation(project(":opendc:opendc-format"))
+ testImplementation(project(":opendc-simulator:opendc-simulator-core"))
+ testImplementation(project(":opendc-format"))
+ testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8") {
+ exclude("org.jetbrains.kotlin", module = "kotlin-reflect")
+ }
+ testImplementation(kotlin("reflect"))
testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
testImplementation("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}")
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/JobState.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/JobState.kt
index 1cb2de97..89849f6a 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/JobState.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/JobState.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
+package org.opendc.workflows.service
-import com.atlarge.opendc.workflows.workload.Job
+import org.opendc.workflows.workload.Job
-class JobState(val job: Job, val submittedAt: Long) {
+public class JobState(public val job: Job, public val submittedAt: Long) {
/**
* A flag to indicate whether this job is finished.
*/
- val isFinished: Boolean
+ public val isFinished: Boolean
get() = tasks.isEmpty()
- val tasks: MutableSet<TaskState> = mutableSetOf()
+ internal val tasks: MutableSet<TaskState> = mutableSetOf()
override fun equals(other: Any?): Boolean = other is JobState && other.job == job
diff --git a/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerListener.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerListener.kt
new file mode 100644
index 00000000..18721889
--- /dev/null
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerListener.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.workflows.service
+
+public interface StageWorkflowSchedulerListener {
+ public fun cycleStarted(scheduler: StageWorkflowService) {}
+ public fun cycleFinished(scheduler: StageWorkflowService) {}
+
+ public fun jobSubmitted(job: JobState) {}
+ public fun jobStarted(job: JobState) {}
+ public fun jobFinished(job: JobState) {}
+
+ public fun taskReady(task: TaskState) {}
+ public fun taskAssigned(task: TaskState) {}
+ public fun taskStarted(task: TaskState) {}
+ public fun taskFinished(task: TaskState) {}
+}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowService.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/StageWorkflowService.kt
index 1193f7b2..3b4e6eab 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowService.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/StageWorkflowService.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,39 +20,37 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
-
-import com.atlarge.odcsim.Domain
-import com.atlarge.odcsim.flow.EventFlow
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.workflows.service.stage.job.JobAdmissionPolicy
-import com.atlarge.opendc.workflows.service.stage.job.JobOrderPolicy
-import com.atlarge.opendc.workflows.service.stage.resource.ResourceFilterPolicy
-import com.atlarge.opendc.workflows.service.stage.resource.ResourceSelectionPolicy
-import com.atlarge.opendc.workflows.service.stage.task.TaskEligibilityPolicy
-import com.atlarge.opendc.workflows.service.stage.task.TaskOrderPolicy
-import com.atlarge.opendc.workflows.workload.Job
-import java.util.PriorityQueue
-import java.util.Queue
+package org.opendc.workflows.service
+
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.ServerEvent
+import org.opendc.compute.core.ServerState
+import org.opendc.compute.core.metal.Node
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.utils.flow.EventFlow
+import org.opendc.workflows.service.stage.job.JobAdmissionPolicy
+import org.opendc.workflows.service.stage.job.JobOrderPolicy
+import org.opendc.workflows.service.stage.resource.ResourceFilterPolicy
+import org.opendc.workflows.service.stage.resource.ResourceSelectionPolicy
+import org.opendc.workflows.service.stage.task.TaskEligibilityPolicy
+import org.opendc.workflows.service.stage.task.TaskOrderPolicy
+import org.opendc.workflows.workload.Job
+import java.time.Clock
+import java.util.*
/**
* A [WorkflowService] that distributes work through a multi-stage process based on the Reference Architecture for
* Topology Scheduling.
*/
-class StageWorkflowService(
- private val domain: Domain,
+public class StageWorkflowService(
+ internal val coroutineScope: CoroutineScope,
+ internal val clock: Clock,
private val provisioningService: ProvisioningService,
mode: WorkflowSchedulerMode,
jobAdmissionPolicy: JobAdmissionPolicy,
@@ -63,7 +59,7 @@ class StageWorkflowService(
taskOrderPolicy: TaskOrderPolicy,
resourceFilterPolicy: ResourceFilterPolicy,
resourceSelectionPolicy: ResourceSelectionPolicy
-) : WorkflowService, CoroutineScope by domain {
+) : WorkflowService {
/**
* The incoming jobs ready to be processed by the scheduler.
@@ -175,7 +171,7 @@ class StageWorkflowService(
private val eventFlow = EventFlow<WorkflowEvent>()
init {
- domain.launch {
+ coroutineScope.launch {
nodes = provisioningService.nodes().toList()
available.addAll(nodes)
}
@@ -191,9 +187,9 @@ class StageWorkflowService(
override val events: Flow<WorkflowEvent> = eventFlow
- override suspend fun submit(job: Job) = withContext(domain.coroutineContext) {
+ override suspend fun submit(job: Job) {
// J1 Incoming Jobs
- val jobInstance = JobState(job, simulationContext.clock.millis())
+ val jobInstance = JobState(job, clock.millis())
val instances = job.tasks.associateWith {
TaskState(jobInstance, it)
}
@@ -241,7 +237,7 @@ class StageWorkflowService(
iterator.remove()
jobQueue.add(jobInstance)
activeJobs += jobInstance
- eventFlow.emit(WorkflowEvent.JobStarted(this, jobInstance.job, simulationContext.clock.millis()))
+ eventFlow.emit(WorkflowEvent.JobStarted(this, jobInstance.job, clock.millis()))
rootListener.jobStarted(jobInstance)
}
@@ -295,7 +291,7 @@ class StageWorkflowService(
taskByServer[server] = instance
server.events
.onEach { event -> if (event is ServerEvent.StateChanged) stateChanged(event.server) }
- .launchIn(this)
+ .launchIn(coroutineScope)
activeTasks += instance
taskQueue.poll()
@@ -310,19 +306,33 @@ class StageWorkflowService(
when (server.state) {
ServerState.ACTIVE -> {
val task = taskByServer.getValue(server)
- task.startedAt = simulationContext.clock.millis()
- eventFlow.emit(WorkflowEvent.TaskStarted(this@StageWorkflowService, task.job.job, task.task, simulationContext.clock.millis()))
+ task.startedAt = clock.millis()
+ eventFlow.emit(
+ WorkflowEvent.TaskStarted(
+ this@StageWorkflowService,
+ task.job.job,
+ task.task,
+ clock.millis()
+ )
+ )
rootListener.taskStarted(task)
}
ServerState.SHUTOFF, ServerState.ERROR -> {
val task = taskByServer.remove(server) ?: throw IllegalStateException()
val job = task.job
task.state = TaskStatus.FINISHED
- task.finishedAt = simulationContext.clock.millis()
+ task.finishedAt = clock.millis()
job.tasks.remove(task)
available += task.host!!
activeTasks -= task
- eventFlow.emit(WorkflowEvent.TaskFinished(this@StageWorkflowService, task.job.job, task.task, simulationContext.clock.millis()))
+ eventFlow.emit(
+ WorkflowEvent.TaskFinished(
+ this@StageWorkflowService,
+ task.job.job,
+ task.task,
+ clock.millis()
+ )
+ )
rootListener.taskFinished(task)
// Add job roots to the scheduling queue
@@ -347,15 +357,15 @@ class StageWorkflowService(
private suspend fun finishJob(job: JobState) {
activeJobs -= job
- eventFlow.emit(WorkflowEvent.JobFinished(this, job.job, simulationContext.clock.millis()))
+ eventFlow.emit(WorkflowEvent.JobFinished(this, job.job, clock.millis()))
rootListener.jobFinished(job)
}
- fun addListener(listener: StageWorkflowSchedulerListener) {
+ public fun addListener(listener: StageWorkflowSchedulerListener) {
rootListener.listeners += listener
}
- fun removeListener(listener: StageWorkflowSchedulerListener) {
+ public fun removeListener(listener: StageWorkflowSchedulerListener) {
rootListener.listeners -= listener
}
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/TaskState.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/TaskState.kt
index acd5731b..ed023c82 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/TaskState.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/TaskState.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,39 +20,39 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
+package org.opendc.workflows.service
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.workflows.workload.Task
+import org.opendc.compute.core.metal.Node
+import org.opendc.workflows.workload.Task
-class TaskState(val job: JobState, val task: Task) {
+public class TaskState(public val job: JobState, public val task: Task) {
/**
* The moment in time the task was started.
*/
- var startedAt: Long = Long.MIN_VALUE
+ public var startedAt: Long = Long.MIN_VALUE
/**
* The moment in time the task was finished.
*/
- var finishedAt: Long = Long.MIN_VALUE
+ public var finishedAt: Long = Long.MIN_VALUE
/**
* The dependencies of this task.
*/
- val dependencies = HashSet<TaskState>()
+ public val dependencies: HashSet<TaskState> = HashSet<TaskState>()
/**
* The dependents of this task.
*/
- val dependents = HashSet<TaskState>()
+ public val dependents: HashSet<TaskState> = HashSet<TaskState>()
/**
* A flag to indicate whether this workflow task instance is a workflow root.
*/
- val isRoot: Boolean
+ public val isRoot: Boolean
get() = dependencies.isEmpty()
- var state: TaskStatus = TaskStatus.CREATED
+ public var state: TaskStatus = TaskStatus.CREATED
set(value) {
field = value
@@ -64,7 +62,7 @@ class TaskState(val job: JobState, val task: Task) {
}
}
- var host: Node? = null
+ public var host: Node? = null
/**
* Mark the specified [TaskView] as terminated.
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/TaskStatus.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/TaskStatus.kt
index c53c6171..99f5bb87 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/TaskStatus.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/TaskStatus.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
+package org.opendc.workflows.service
/**
* The state of a workflow task.
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowEvent.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowEvent.kt
index 2ca5a19d..dadccb50 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowEvent.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowEvent.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +20,10 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
+package org.opendc.workflows.service
-import com.atlarge.opendc.workflows.workload.Job
-import com.atlarge.opendc.workflows.workload.Task
+import org.opendc.workflows.workload.Job
+import org.opendc.workflows.workload.Task
/**
* An event emitted by the [WorkflowService].
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowSchedulerMode.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowSchedulerMode.kt
index 776f0b07..d03adc61 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowSchedulerMode.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowSchedulerMode.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,32 +20,31 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
+package org.opendc.workflows.service
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.workflows.service.stage.StagePolicy
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.yield
+import org.opendc.workflows.service.stage.StagePolicy
/**
* The operating mode of a workflow scheduler.
*/
-sealed class WorkflowSchedulerMode : StagePolicy<WorkflowSchedulerMode.Logic> {
+public sealed class WorkflowSchedulerMode : StagePolicy<WorkflowSchedulerMode.Logic> {
/**
* The logic for operating the cycles of a workflow scheduler.
*/
- interface Logic {
+ public interface Logic {
/**
* Request a new scheduling cycle to be performed.
*/
- suspend fun requestCycle()
+ public suspend fun requestCycle()
}
/**
* An interactive scheduler immediately triggers a new scheduling cycle when a workflow is received.
*/
- object Interactive : WorkflowSchedulerMode() {
+ public object Interactive : WorkflowSchedulerMode() {
override fun invoke(scheduler: StageWorkflowService): Logic = object : Logic {
override suspend fun requestCycle() {
yield()
@@ -61,18 +58,17 @@ sealed class WorkflowSchedulerMode : StagePolicy<WorkflowSchedulerMode.Logic> {
/**
* A batch scheduler triggers a scheduling cycle every time quantum if needed.
*/
- data class Batch(val quantum: Long) : WorkflowSchedulerMode() {
+ public data class Batch(val quantum: Long) : WorkflowSchedulerMode() {
private var next: kotlinx.coroutines.Job? = null
override fun invoke(scheduler: StageWorkflowService): Logic = object : Logic {
override suspend fun requestCycle() {
- val ctx = simulationContext
if (next == null) {
// In batch mode, we assume that the scheduler runs at a fixed slot every time
// quantum (e.g t=0, t=60, t=120). We calculate here the delay until the next scheduling slot.
- val delay = quantum - (ctx.clock.millis() % quantum)
+ val delay = quantum - (scheduler.clock.millis() % quantum)
- val job = ctx.domain.launch {
+ val job = scheduler.coroutineScope.launch {
delay(delay)
next = null
scheduler.schedule()
@@ -88,16 +84,15 @@ sealed class WorkflowSchedulerMode : StagePolicy<WorkflowSchedulerMode.Logic> {
/**
* A scheduling cycle is triggered at a random point in time.
*/
- data class Random(private val random: java.util.Random = java.util.Random(123)) : WorkflowSchedulerMode() {
+ public data class Random(private val random: java.util.Random = java.util.Random(123)) : WorkflowSchedulerMode() {
private var next: kotlinx.coroutines.Job? = null
override fun invoke(scheduler: StageWorkflowService): Logic = object : Logic {
override suspend fun requestCycle() {
- val ctx = simulationContext
if (next == null) {
val delay = random.nextInt(200).toLong()
- val job = ctx.domain.launch {
+ val job = scheduler.coroutineScope.launch {
delay(delay)
next = null
scheduler.schedule()
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowService.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowService.kt
index a60ba0e2..319a8b85 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/WorkflowService.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/WorkflowService.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
+package org.opendc.workflows.service
-import com.atlarge.opendc.core.services.AbstractServiceKey
-import com.atlarge.opendc.workflows.workload.Job
-import java.util.UUID
import kotlinx.coroutines.flow.Flow
+import org.opendc.core.services.AbstractServiceKey
+import org.opendc.workflows.workload.Job
+import java.util.*
/**
* A service for cloud workflow management.
@@ -48,5 +46,5 @@ public interface WorkflowService {
/**
* The service key for the workflow scheduler.
*/
- companion object Key : AbstractServiceKey<WorkflowService>(UUID.randomUUID(), "workflows")
+ public companion object Key : AbstractServiceKey<WorkflowService>(UUID.randomUUID(), "workflows")
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/StagePolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/StagePolicy.kt
index c7cc3d84..d76579f9 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/StagePolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/StagePolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage
+package org.opendc.workflows.service.stage
-import com.atlarge.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.StageWorkflowService
import java.io.Serializable
/**
* A scheduling stage policy.
*/
-interface StagePolicy<T : Any> : Serializable {
+public interface StagePolicy<T : Any> : Serializable {
/**
* Build the logic of the stage policy.
*/
- operator fun invoke(scheduler: StageWorkflowService): T
+ public operator fun invoke(scheduler: StageWorkflowService): T
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/DurationJobOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/DurationJobOrderPolicy.kt
index bbdb9f71..1190a408 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/DurationJobOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/DurationJobOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,19 +20,19 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.workload.Job
-import com.atlarge.opendc.workflows.workload.Task
-import com.atlarge.opendc.workflows.workload.WORKFLOW_TASK_DEADLINE
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.workload.Job
+import org.opendc.workflows.workload.Task
+import org.opendc.workflows.workload.WORKFLOW_TASK_DEADLINE
/**
* A [JobOrderPolicy] that orders jobs based on its critical path length.
*/
-data class DurationJobOrderPolicy(val ascending: Boolean = true) : JobOrderPolicy {
+public data class DurationJobOrderPolicy(val ascending: Boolean = true) : JobOrderPolicy {
override fun invoke(scheduler: StageWorkflowService): Comparator<JobState> =
object : Comparator<JobState>, StageWorkflowSchedulerListener {
private val results = HashMap<Job, Long>()
@@ -72,7 +70,7 @@ data class DurationJobOrderPolicy(val ascending: Boolean = true) : JobOrderPolic
*
* @return The list of tasks within the job topologically sorted.
*/
-fun Job.toposort(): List<Task> {
+public fun Job.toposort(): List<Task> {
val res = mutableListOf<Task>()
val visited = mutableSetOf<Task>()
val adjacent = mutableMapOf<Task, MutableList<Task>>()
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/JobAdmissionPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/JobAdmissionPolicy.kt
index 535d7792..0e5a42c0 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/JobAdmissionPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/JobAdmissionPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,23 +20,23 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.stage.StagePolicy
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.stage.StagePolicy
/**
* A policy interface for admitting [JobState]s to a scheduling cycle.
*/
-interface JobAdmissionPolicy : StagePolicy<JobAdmissionPolicy.Logic> {
- interface Logic {
+public interface JobAdmissionPolicy : StagePolicy<JobAdmissionPolicy.Logic> {
+ public interface Logic {
/**
* Determine whether the specified [JobState] should be admitted to the scheduling cycle.
*
* @param job The workflow that has been submitted.
* @return The advice for admitting the job.
*/
- operator fun invoke(job: JobState): Advice
+ public operator fun invoke(job: JobState): Advice
}
/**
@@ -48,7 +46,7 @@ interface JobAdmissionPolicy : StagePolicy<JobAdmissionPolicy.Logic> {
* @property stop A flag to indicate the scheduler should immediately stop admitting jobs to the scheduling queue and wait
* for the next scheduling cycle.
*/
- enum class Advice(val admit: Boolean, val stop: Boolean) {
+ public enum class Advice(public val admit: Boolean, public val stop: Boolean) {
/**
* Admit the current job to the scheduling queue and continue admitting jobs.
*/
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/JobOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/JobOrderPolicy.kt
index ba57f064..83d42b2d 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/JobOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/JobOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.stage.StagePolicy
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.stage.StagePolicy
/**
* A policy interface for ordering admitted workflows in the scheduling queue.
*/
-interface JobOrderPolicy : StagePolicy<Comparator<JobState>>
+public interface JobOrderPolicy : StagePolicy<Comparator<JobState>>
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/LimitJobAdmissionPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/LimitJobAdmissionPolicy.kt
index 6b1faf20..6f6ccb50 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/LimitJobAdmissionPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/LimitJobAdmissionPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowService
/**
* A [JobAdmissionPolicy] that limits the amount of active jobs in the system.
*
* @property limit The maximum number of concurrent jobs in the system.
*/
-data class LimitJobAdmissionPolicy(val limit: Int) : JobAdmissionPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : JobAdmissionPolicy.Logic {
+public data class LimitJobAdmissionPolicy(public val limit: Int) : JobAdmissionPolicy {
+ override fun invoke(scheduler: StageWorkflowService): JobAdmissionPolicy.Logic = object : JobAdmissionPolicy.Logic {
override fun invoke(
job: JobState
): JobAdmissionPolicy.Advice =
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/LoadJobAdmissionPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/LoadJobAdmissionPolicy.kt
index e1c27472..4f0c269a 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/LoadJobAdmissionPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/LoadJobAdmissionPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowService
/**
* A [JobAdmissionPolicy] that limits the amount of jobs based on the average system load.
*
* @property limit The maximum load before stopping admission.
*/
-data class LoadJobAdmissionPolicy(val limit: Double) : JobAdmissionPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : JobAdmissionPolicy.Logic {
+public data class LoadJobAdmissionPolicy(public val limit: Double) : JobAdmissionPolicy {
+ override fun invoke(scheduler: StageWorkflowService): JobAdmissionPolicy.Logic = object : JobAdmissionPolicy.Logic {
override fun invoke(
job: JobState
): JobAdmissionPolicy.Advice =
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/NullJobAdmissionPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/NullJobAdmissionPolicy.kt
index 46888467..ac74f090 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/NullJobAdmissionPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/NullJobAdmissionPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowService
/**
* A [JobAdmissionPolicy] that admits all jobs.
*/
-object NullJobAdmissionPolicy : JobAdmissionPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : JobAdmissionPolicy.Logic {
+public object NullJobAdmissionPolicy : JobAdmissionPolicy {
+ override fun invoke(scheduler: StageWorkflowService): JobAdmissionPolicy.Logic = object : JobAdmissionPolicy.Logic {
override fun invoke(job: JobState): JobAdmissionPolicy.Advice = JobAdmissionPolicy.Advice.ADMIT
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/RandomJobOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/RandomJobOrderPolicy.kt
index 14a3d98d..6c747261 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/RandomJobOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/RandomJobOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,21 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.workload.Job
-import java.util.Random
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.workload.Job
+import java.util.*
+import kotlin.collections.HashMap
+import kotlin.collections.getValue
+import kotlin.collections.set
/**
* A [JobOrderPolicy] that randomly orders jobs.
*/
-object RandomJobOrderPolicy : JobOrderPolicy {
+public object RandomJobOrderPolicy : JobOrderPolicy {
override fun invoke(scheduler: StageWorkflowService): Comparator<JobState> =
object : Comparator<JobState>, StageWorkflowSchedulerListener {
private val random = Random(123)
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/SizeJobOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/SizeJobOrderPolicy.kt
index 3bce43cf..c1c244c3 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/SizeJobOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/SizeJobOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowService
/**
* A [SizeJobOrderPolicy] that orders jobs based on the number of tasks it has.
*/
-data class SizeJobOrderPolicy(val ascending: Boolean = true) : JobOrderPolicy {
- override fun invoke(scheduler: StageWorkflowService) =
- compareBy<JobState> { it.tasks.size.let { if (ascending) it else -it } }
+public data class SizeJobOrderPolicy(public val ascending: Boolean = true) : JobOrderPolicy {
+ override fun invoke(scheduler: StageWorkflowService): Comparator<JobState> =
+ compareBy { it.tasks.size.let { if (ascending) it else -it } }
override fun toString(): String {
return "Job-Size(${if (ascending) "asc" else "desc"})"
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/SubmissionTimeJobOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/SubmissionTimeJobOrderPolicy.kt
index d6e24b2b..005f8153 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/job/SubmissionTimeJobOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/job/SubmissionTimeJobOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.job
+package org.opendc.workflows.service.stage.job
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowService
/**
* A [JobOrderPolicy] orders jobs in FIFO order.
*/
-data class SubmissionTimeJobOrderPolicy(val ascending: Boolean = true) : JobOrderPolicy {
- override fun invoke(scheduler: StageWorkflowService) =
- compareBy<JobState> { it.submittedAt.let { if (ascending) it else -it } }
+public data class SubmissionTimeJobOrderPolicy(public val ascending: Boolean = true) : JobOrderPolicy {
+ override fun invoke(scheduler: StageWorkflowService): Comparator<JobState> =
+ compareBy { it.submittedAt.let { if (ascending) it else -it } }
override fun toString(): String {
return "Submission-Time(${if (ascending) "asc" else "desc"})"
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/FirstFitResourceSelectionPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/FirstFitResourceSelectionPolicy.kt
index a5671d45..8dc323ec 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/FirstFitResourceSelectionPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/FirstFitResourceSelectionPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.resource
+package org.opendc.workflows.service.stage.resource
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.workflows.service.StageWorkflowService
+import org.opendc.compute.core.metal.Node
+import org.opendc.workflows.service.StageWorkflowService
/**
* A [ResourceSelectionPolicy] that selects the first machine that is available.
*/
-object FirstFitResourceSelectionPolicy : ResourceSelectionPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : Comparator<Node> {
- override fun compare(o1: Node, o2: Node): Int = 1
- }
+public object FirstFitResourceSelectionPolicy : ResourceSelectionPolicy {
+ override fun invoke(scheduler: StageWorkflowService): Comparator<Node> =
+ Comparator<Node> { _, _ -> 1 }
override fun toString(): String = "First-Fit"
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/FunctionalResourceFilterPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/FunctionalResourceFilterPolicy.kt
index 0e83d8d7..ac79a9ce 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/FunctionalResourceFilterPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/FunctionalResourceFilterPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.resource
+package org.opendc.workflows.service.stage.resource
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.compute.core.metal.Node
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [ResourceFilterPolicy] based on the amount of cores available on the machine and the cores required for
* the task.
*/
-object FunctionalResourceFilterPolicy : ResourceFilterPolicy {
+public object FunctionalResourceFilterPolicy : ResourceFilterPolicy {
override fun invoke(scheduler: StageWorkflowService): ResourceFilterPolicy.Logic =
object : ResourceFilterPolicy.Logic {
override fun invoke(hosts: Sequence<Node>, task: TaskState): Sequence<Node> =
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/RandomResourceSelectionPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/RandomResourceSelectionPolicy.kt
index 9b05cbac..caf87c70 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/RandomResourceSelectionPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/RandomResourceSelectionPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.resource
+package org.opendc.workflows.service.stage.resource
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import java.util.Random
+import org.opendc.compute.core.metal.Node
+import org.opendc.workflows.service.StageWorkflowService
+import java.util.*
/**
* A [ResourceSelectionPolicy] that randomly orders the machines.
*/
-object RandomResourceSelectionPolicy : ResourceSelectionPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : Comparator<Node> {
+public object RandomResourceSelectionPolicy : ResourceSelectionPolicy {
+ override fun invoke(scheduler: StageWorkflowService): Comparator<Node> = object : Comparator<Node> {
private val ids: Map<Node, Long>
init {
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/ResourceFilterPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/ResourceFilterPolicy.kt
index 28ef970f..4923a34b 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/ResourceFilterPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/ResourceFilterPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,19 +20,19 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.resource
+package org.opendc.workflows.service.stage.resource
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.workflows.service.TaskState
-import com.atlarge.opendc.workflows.service.stage.StagePolicy
+import org.opendc.compute.core.metal.Node
+import org.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.stage.StagePolicy
/**
* This interface represents stages **R2**, **R3** and **R4** stage of the Reference Architecture for Schedulers and
* acts as a filter yielding a list of resources with sufficient resource-capacities, based on fixed or dynamic
* requirements, and on predicted or monitored information about processing unit availability, memory occupancy, etc.
*/
-interface ResourceFilterPolicy : StagePolicy<ResourceFilterPolicy.Logic> {
- interface Logic {
+public interface ResourceFilterPolicy : StagePolicy<ResourceFilterPolicy.Logic> {
+ public interface Logic {
/**
* Filter the list of machines based on dynamic information.
*
@@ -42,6 +40,6 @@ interface ResourceFilterPolicy : StagePolicy<ResourceFilterPolicy.Logic> {
* @param task The task that is to be scheduled.
* @return The machines on which the task can be scheduled.
*/
- operator fun invoke(hosts: Sequence<Node>, task: TaskState): Sequence<Node>
+ public operator fun invoke(hosts: Sequence<Node>, task: TaskState): Sequence<Node>
}
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/ResourceSelectionPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/ResourceSelectionPolicy.kt
index 43053097..990b990a 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/resource/ResourceSelectionPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/resource/ResourceSelectionPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +20,13 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.resource
+package org.opendc.workflows.service.stage.resource
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.workflows.service.stage.StagePolicy
+import org.opendc.compute.core.metal.Node
+import org.opendc.workflows.service.stage.StagePolicy
/**
* This interface represents the **R5** stage of the Reference Architecture for Schedulers and matches the the selected
* task with a (set of) resource(s), using policies such as First-Fit, Worst-Fit, and Best-Fit.
*/
-interface ResourceSelectionPolicy : StagePolicy<Comparator<Node>>
+public interface ResourceSelectionPolicy : StagePolicy<Comparator<Node>>
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/ActiveTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/ActiveTaskOrderPolicy.kt
index b084d26c..6a465746 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/ActiveTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/ActiveTaskOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskOrderPolicy] that orders tasks based on the number of active relative tasks (w.r.t. its job) in the system.
*/
-data class ActiveTaskOrderPolicy(val ascending: Boolean = true) : TaskOrderPolicy {
+public data class ActiveTaskOrderPolicy(public val ascending: Boolean = true) : TaskOrderPolicy {
override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> =
object : Comparator<TaskState>, StageWorkflowSchedulerListener {
private val active = mutableMapOf<JobState, Int>()
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/BalancingTaskEligibilityPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/BalancingTaskEligibilityPolicy.kt
index 2255d40c..f3f19ef5 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/BalancingTaskEligibilityPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/BalancingTaskEligibilityPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +20,12 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
import kotlin.math.max
/**
@@ -37,7 +35,7 @@ import kotlin.math.max
* @property tolerance The maximum difference from the average number of tasks per job in the system as a fraction of
* the average.
*/
-data class BalancingTaskEligibilityPolicy(val tolerance: Double = 1.5) : TaskEligibilityPolicy {
+public data class BalancingTaskEligibilityPolicy(public val tolerance: Double = 1.5) : TaskEligibilityPolicy {
override fun invoke(scheduler: StageWorkflowService): TaskEligibilityPolicy.Logic =
object : TaskEligibilityPolicy.Logic, StageWorkflowSchedulerListener {
private val active = mutableMapOf<JobState, Int>()
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/CompletionTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/CompletionTaskOrderPolicy.kt
index d0cf1374..0020023f 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/CompletionTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/CompletionTaskOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskOrderPolicy] that orders tasks based on the number of completed relative tasks.
*/
-data class CompletionTaskOrderPolicy(val ascending: Boolean = true) : TaskOrderPolicy {
+public data class CompletionTaskOrderPolicy(public val ascending: Boolean = true) : TaskOrderPolicy {
override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> =
object : Comparator<TaskState>, StageWorkflowSchedulerListener {
private val finished = mutableMapOf<JobState, Int>()
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DependenciesTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DependenciesTaskOrderPolicy.kt
index 73d83d21..a9f5eb84 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DependenciesTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DependenciesTaskOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskOrderPolicy] that orders tasks based on the number of dependency tasks it has.
*/
-data class DependenciesTaskOrderPolicy(val ascending: Boolean = true) : TaskOrderPolicy {
- override fun invoke(scheduler: StageWorkflowService) = compareBy<TaskState> {
+public data class DependenciesTaskOrderPolicy(public val ascending: Boolean = true) : TaskOrderPolicy {
+ override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> = compareBy<TaskState> {
it.task.dependencies.size.let { if (ascending) it else -it }
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DependentsTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DependentsTaskOrderPolicy.kt
index 85b3543f..e5a9f159 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DependentsTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DependentsTaskOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskOrderPolicy] that orders tasks based on the number of dependent tasks it has.
*/
-data class DependentsTaskOrderPolicy(val ascending: Boolean = true) : TaskOrderPolicy {
- override fun invoke(scheduler: StageWorkflowService) = compareBy<TaskState> {
+public data class DependentsTaskOrderPolicy(public val ascending: Boolean = true) : TaskOrderPolicy {
+ override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> = compareBy<TaskState> {
it.dependents.size.let { if (ascending) it else -it }
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DurationHistoryTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DurationHistoryTaskOrderPolicy.kt
index 426a76a4..7ce8ccce 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DurationHistoryTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DurationHistoryTaskOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskOrderPolicy] that orders tasks based on the average duration of the preceding tasks in the job.
*/
-data class DurationHistoryTaskOrderPolicy(val ascending: Boolean = true) : TaskOrderPolicy {
-
+public data class DurationHistoryTaskOrderPolicy(public val ascending: Boolean = true) : TaskOrderPolicy {
override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> =
object : Comparator<TaskState>, StageWorkflowSchedulerListener {
private val results = HashMap<JobState, MutableList<Long>>()
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DurationTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DurationTaskOrderPolicy.kt
index 23b47891..3674eb01 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/DurationTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/DurationTaskOrderPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,18 +20,22 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
-import com.atlarge.opendc.workflows.workload.WORKFLOW_TASK_DEADLINE
-import java.util.UUID
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
+import org.opendc.workflows.workload.WORKFLOW_TASK_DEADLINE
+import java.util.*
+import kotlin.collections.HashMap
+import kotlin.collections.getValue
+import kotlin.collections.minusAssign
+import kotlin.collections.set
/**
* A [TaskOrderPolicy] orders tasks based on the pre-specified (approximate) duration of the task.
*/
-data class DurationTaskOrderPolicy(val ascending: Boolean = true) : TaskOrderPolicy {
+public data class DurationTaskOrderPolicy(public val ascending: Boolean = true) : TaskOrderPolicy {
override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> =
object : Comparator<TaskState>, StageWorkflowSchedulerListener {
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LimitPerJobTaskEligibilityPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LimitPerJobTaskEligibilityPolicy.kt
index c039bf6f..2dddbc7c 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LimitPerJobTaskEligibilityPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LimitPerJobTaskEligibilityPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.JobState
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.JobState
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskEligibilityPolicy] that limits the number of active tasks of a job in the system.
*/
-data class LimitPerJobTaskEligibilityPolicy(val limit: Int) : TaskEligibilityPolicy {
+public data class LimitPerJobTaskEligibilityPolicy(public val limit: Int) : TaskEligibilityPolicy {
override fun invoke(scheduler: StageWorkflowService): TaskEligibilityPolicy.Logic =
object : TaskEligibilityPolicy.Logic, StageWorkflowSchedulerListener {
private val active = mutableMapOf<JobState, Int>()
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LimitTaskEligibilityPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LimitTaskEligibilityPolicy.kt
index 75322ef5..fdc1fd5e 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LimitTaskEligibilityPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LimitTaskEligibilityPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskEligibilityPolicy] that limits the total number of active tasks in the system.
*/
-data class LimitTaskEligibilityPolicy(val limit: Int) : TaskEligibilityPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : TaskEligibilityPolicy.Logic {
+public data class LimitTaskEligibilityPolicy(val limit: Int) : TaskEligibilityPolicy {
+ override fun invoke(scheduler: StageWorkflowService): TaskEligibilityPolicy.Logic = object : TaskEligibilityPolicy.Logic {
override fun invoke(
task: TaskState
): TaskEligibilityPolicy.Advice =
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LoadTaskEligibilityPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LoadTaskEligibilityPolicy.kt
index 090f7be7..a80a8c63 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/LoadTaskEligibilityPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/LoadTaskEligibilityPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +20,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskEligibilityPolicy] that limits the number of active tasks in the system based on the average system load.
*/
-data class LoadTaskEligibilityPolicy(val limit: Double) : TaskEligibilityPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : TaskEligibilityPolicy.Logic {
+public data class LoadTaskEligibilityPolicy(val limit: Double) : TaskEligibilityPolicy {
+ override fun invoke(scheduler: StageWorkflowService): TaskEligibilityPolicy.Logic = object : TaskEligibilityPolicy.Logic {
override fun invoke(
task: TaskState
): TaskEligibilityPolicy.Advice =
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/NullTaskEligibilityPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/NullTaskEligibilityPolicy.kt
index 889f2ab5..b40f9823 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/NullTaskEligibilityPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/NullTaskEligibilityPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,15 +20,15 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskEligibilityPolicy] that always allows new tasks to enter.
*/
-object NullTaskEligibilityPolicy : TaskEligibilityPolicy {
+public object NullTaskEligibilityPolicy : TaskEligibilityPolicy {
override fun invoke(scheduler: StageWorkflowService): TaskEligibilityPolicy.Logic = Logic
private object Logic : TaskEligibilityPolicy.Logic {
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/RandomTaskEligibilityPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/RandomTaskEligibilityPolicy.kt
index d6f49d14..a0691b23 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/RandomTaskEligibilityPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/RandomTaskEligibilityPolicy.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +20,17 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
-import java.util.Random
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
+import java.util.*
/**
* A [TaskEligibilityPolicy] that randomly accepts tasks in the system with some [probability].
*/
-data class RandomTaskEligibilityPolicy(val probability: Double = 0.5) : TaskEligibilityPolicy {
- override fun invoke(scheduler: StageWorkflowService) = object : TaskEligibilityPolicy.Logic {
+public data class RandomTaskEligibilityPolicy(val probability: Double = 0.5) : TaskEligibilityPolicy {
+ override fun invoke(scheduler: StageWorkflowService): TaskEligibilityPolicy.Logic = object : TaskEligibilityPolicy.Logic {
val random = Random(123)
override fun invoke(task: TaskState): TaskEligibilityPolicy.Advice =
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/RandomTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/RandomTaskOrderPolicy.kt
index 4c309085..890e7165 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/RandomTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/RandomTaskOrderPolicy.kt
@@ -22,18 +22,18 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowSchedulerListener
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
-import com.atlarge.opendc.workflows.workload.Task
+import org.opendc.workflows.service.StageWorkflowSchedulerListener
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
+import org.opendc.workflows.workload.Task
import kotlin.random.Random
/**
* A [TaskOrderPolicy] that orders the tasks randomly.
*/
-object RandomTaskOrderPolicy : TaskOrderPolicy {
+public object RandomTaskOrderPolicy : TaskOrderPolicy {
override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> =
object : Comparator<TaskState>, StageWorkflowSchedulerListener {
private val random = Random(123)
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/SubmissionTimeTaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/SubmissionTimeTaskOrderPolicy.kt
index a261965f..6b0199b8 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/SubmissionTimeTaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/SubmissionTimeTaskOrderPolicy.kt
@@ -22,16 +22,16 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.StageWorkflowService
-import com.atlarge.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.StageWorkflowService
+import org.opendc.workflows.service.TaskState
/**
* A [TaskOrderPolicy] that orders tasks based on the order of arrival in the queue.
*/
-data class SubmissionTimeTaskOrderPolicy(val ascending: Boolean = true) : TaskOrderPolicy {
- override fun invoke(scheduler: StageWorkflowService) = compareBy<TaskState> {
+public data class SubmissionTimeTaskOrderPolicy(public val ascending: Boolean = true) : TaskOrderPolicy {
+ override fun invoke(scheduler: StageWorkflowService): Comparator<TaskState> = compareBy<TaskState> {
it.job.submittedAt.let { if (ascending) it else -it }
}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/TaskEligibilityPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/TaskEligibilityPolicy.kt
index 72a7fdd0..37597709 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/TaskEligibilityPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/TaskEligibilityPolicy.kt
@@ -22,23 +22,23 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.TaskState
-import com.atlarge.opendc.workflows.service.stage.StagePolicy
+import org.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.stage.StagePolicy
/**
* A policy interface for determining the eligibility of tasks in a scheduling cycle.
*/
-interface TaskEligibilityPolicy : StagePolicy<TaskEligibilityPolicy.Logic> {
- interface Logic {
+public interface TaskEligibilityPolicy : StagePolicy<TaskEligibilityPolicy.Logic> {
+ public interface Logic {
/**
* Determine whether the specified [TaskState] is eligible to be scheduled.
*
* @param task The task instance to schedule.
* @return The advice for marking the task.
*/
- operator fun invoke(task: TaskState): Advice
+ public operator fun invoke(task: TaskState): Advice
}
/**
@@ -48,7 +48,7 @@ interface TaskEligibilityPolicy : StagePolicy<TaskEligibilityPolicy.Logic> {
* @property stop A flag to indicate the scheduler should immediately stop admitting jobs to the scheduling queue and wait
* for the next scheduling cycle.
*/
- enum class Advice(val admit: Boolean, val stop: Boolean) {
+ public enum class Advice(public val admit: Boolean, public val stop: Boolean) {
/**
* Admit the current job to the scheduling queue and continue admitting jobs.
*/
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/TaskOrderPolicy.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/TaskOrderPolicy.kt
index e74082c2..5feac6d0 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/stage/task/TaskOrderPolicy.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/service/stage/task/TaskOrderPolicy.kt
@@ -22,13 +22,13 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service.stage.task
+package org.opendc.workflows.service.stage.task
-import com.atlarge.opendc.workflows.service.TaskState
-import com.atlarge.opendc.workflows.service.stage.StagePolicy
+import org.opendc.workflows.service.TaskState
+import org.opendc.workflows.service.stage.StagePolicy
/**
* This interface represents the **T2** stage of the Reference Architecture for Topology Schedulers and provides the
* scheduler with a sorted list of tasks to schedule.
*/
-interface TaskOrderPolicy : StagePolicy<Comparator<TaskState>>
+public interface TaskOrderPolicy : StagePolicy<Comparator<TaskState>>
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Job.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Job.kt
index 02969d8a..f1cfdf65 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Job.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Job.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2019 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,11 +20,11 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.workload
+package org.opendc.workflows.workload
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.core.workload.Workload
-import java.util.UUID
+import org.opendc.core.User
+import org.opendc.core.workload.Workload
+import java.util.*
/**
* A workload that represents a directed acyclic graph (DAG) of tasks with control and data dependencies between tasks.
@@ -37,12 +35,12 @@ import java.util.UUID
* @property tasks The tasks that are part of this workflow.
* @property metadata Additional metadata for the job.
*/
-data class Job(
+public data class Job(
override val uid: UUID,
override val name: String,
override val owner: User,
- val tasks: Set<Task>,
- val metadata: Map<String, Any> = emptyMap()
+ public val tasks: Set<Task>,
+ public val metadata: Map<String, Any> = emptyMap()
) : Workload {
override fun equals(other: Any?): Boolean = other is Job && uid == other.uid
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Metadata.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Metadata.kt
index 067f1179..d02e2b4e 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Metadata.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Metadata.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.workload
+package org.opendc.workflows.workload
/**
* Meta-data key for the deadline of a task.
*/
-const val WORKFLOW_TASK_DEADLINE = "workflow:task:deadline"
+public const val WORKFLOW_TASK_DEADLINE: String = "workflow:task:deadline"
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Task.kt b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Task.kt
index 82521faa..1834a4c8 100644
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/workload/Task.kt
+++ b/simulator/opendc-workflows/src/main/kotlin/org/opendc/workflows/workload/Task.kt
@@ -22,11 +22,11 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.workload
+package org.opendc.workflows.workload
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.core.Identity
-import java.util.UUID
+import org.opendc.compute.core.image.Image
+import org.opendc.core.Identity
+import java.util.*
/**
* A stage of a [Job].
@@ -37,12 +37,12 @@ import java.util.UUID
* @property dependencies The dependencies of this task in order for it to execute.
* @property metadata Additional metadata for this task.
*/
-data class Task(
+public data class Task(
override val uid: UUID,
override val name: String,
- val image: Image,
- val dependencies: Set<Task>,
- val metadata: Map<String, Any> = emptyMap()
+ public val image: Image,
+ public val dependencies: Set<Task>,
+ public val metadata: Map<String, Any> = emptyMap()
) : Identity {
override fun equals(other: Any?): Boolean = other is Task && uid == other.uid
diff --git a/simulator/opendc/opendc-workflows/src/test/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt b/simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt
index 5c129e37..90cf5b99 100644
--- a/simulator/opendc/opendc-workflows/src/test/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt
+++ b/simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt
@@ -22,35 +22,36 @@
* SOFTWARE.
*/
-package com.atlarge.opendc.workflows.service
+package org.opendc.workflows.service
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.format.environment.sc18.Sc18EnvironmentReader
-import com.atlarge.opendc.format.trace.gwf.GwfTraceReader
-import com.atlarge.opendc.workflows.service.stage.job.NullJobAdmissionPolicy
-import com.atlarge.opendc.workflows.service.stage.job.SubmissionTimeJobOrderPolicy
-import com.atlarge.opendc.workflows.service.stage.resource.FirstFitResourceSelectionPolicy
-import com.atlarge.opendc.workflows.service.stage.resource.FunctionalResourceFilterPolicy
-import com.atlarge.opendc.workflows.service.stage.task.NullTaskEligibilityPolicy
-import com.atlarge.opendc.workflows.service.stage.task.SubmissionTimeTaskOrderPolicy
-import java.util.ServiceLoader
-import kotlin.math.max
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestCoroutineScope
import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertNotEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
+import org.opendc.compute.core.metal.service.ProvisioningService
+import org.opendc.format.environment.sc18.Sc18EnvironmentReader
+import org.opendc.format.trace.gwf.GwfTraceReader
+import org.opendc.simulator.utils.DelayControllerClockAdapter
+import org.opendc.workflows.service.stage.job.NullJobAdmissionPolicy
+import org.opendc.workflows.service.stage.job.SubmissionTimeJobOrderPolicy
+import org.opendc.workflows.service.stage.resource.FirstFitResourceSelectionPolicy
+import org.opendc.workflows.service.stage.resource.FunctionalResourceFilterPolicy
+import org.opendc.workflows.service.stage.task.NullTaskEligibilityPolicy
+import org.opendc.workflows.service.stage.task.SubmissionTimeTaskOrderPolicy
+import kotlin.math.max
/**
* Integration test suite for the [StageWorkflowService].
*/
@DisplayName("StageWorkflowService")
+@OptIn(ExperimentalCoroutinesApi::class)
internal class StageWorkflowSchedulerIntegrationTest {
/**
* A large integration test where we check whether all tasks in some trace are executed correctly.
@@ -63,16 +64,16 @@ internal class StageWorkflowSchedulerIntegrationTest {
var tasksStarted = 0L
var tasksFinished = 0L
- val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
- val system = provider(name = "sim")
+ val testScope = TestCoroutineScope()
+ val clock = DelayControllerClockAdapter(testScope)
- val schedulerDomain = system.newDomain(name = "scheduler")
- val schedulerAsync = schedulerDomain.async {
+ val schedulerAsync = testScope.async {
val environment = Sc18EnvironmentReader(object {}.javaClass.getResourceAsStream("/environment.json"))
- .use { it.construct(system.newDomain("topology")) }
+ .use { it.construct(testScope, clock) }
StageWorkflowService(
- schedulerDomain,
+ testScope,
+ clock,
environment.platforms[0].zones[0].services[ProvisioningService],
mode = WorkflowSchedulerMode.Batch(100),
jobAdmissionPolicy = NullJobAdmissionPolicy,
@@ -84,9 +85,7 @@ internal class StageWorkflowSchedulerIntegrationTest {
)
}
- val broker = system.newDomain(name = "broker")
-
- broker.launch {
+ testScope.launch {
val scheduler = schedulerAsync.await()
scheduler.events
.onEach { event ->
@@ -100,24 +99,21 @@ internal class StageWorkflowSchedulerIntegrationTest {
.collect()
}
- broker.launch {
- val ctx = simulationContext
+ testScope.launch {
val reader = GwfTraceReader(object {}.javaClass.getResourceAsStream("/trace.gwf"))
val scheduler = schedulerAsync.await()
while (reader.hasNext()) {
val (time, job) = reader.next()
jobsSubmitted++
- delay(max(0, time * 1000 - ctx.clock.millis()))
+ delay(max(0, time * 1000 - clock.millis()))
scheduler.submit(job)
}
}
- runBlocking {
- system.run()
- system.terminate()
- }
+ testScope.advanceUntilIdle()
+ assertNotEquals(0, jobsSubmitted, "No jobs submitted")
assertEquals(jobsSubmitted, jobsStarted, "Not all submitted jobs started")
assertEquals(jobsSubmitted, jobsFinished, "Not all started jobs finished")
assertEquals(tasksStarted, tasksFinished, "Not all started tasks finished")
diff --git a/simulator/opendc/opendc-workflows/src/test/resources/environment.json b/simulator/opendc-workflows/src/test/resources/environment.json
index 0965b250..0965b250 100644
--- a/simulator/opendc/opendc-workflows/src/test/resources/environment.json
+++ b/simulator/opendc-workflows/src/test/resources/environment.json
diff --git a/simulator/opendc/opendc-workflows/src/test/resources/trace.gwf b/simulator/opendc-workflows/src/test/resources/trace.gwf
index d264b9c3..d264b9c3 100644
--- a/simulator/opendc/opendc-workflows/src/test/resources/trace.gwf
+++ b/simulator/opendc-workflows/src/test/resources/trace.gwf
diff --git a/simulator/opendc/README.md b/simulator/opendc/README.md
deleted file mode 100644
index e3c65ba7..00000000
--- a/simulator/opendc/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-<h1 align="center">
- <a href="http://opendc.org/">
- <img src="../misc/artwork/logo.png" width="100" alt="OpenDC">
- </a>
- <br>
- OpenDC
-</h1>
-
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt
deleted file mode 100644
index e4da557b..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.execution
-
-import kotlinx.coroutines.CancellationException
-
-/**
- * This exception is thrown by the underlying [ServerContext] to indicate that a shutdown flow
- * has been sent to the server.
- */
-public class ShutdownException(message: String? = null, override val cause: Throwable? = null) : CancellationException(message)
-
-/**
- * This method terminates the current active coroutine if the specified [CancellationException] is caused
- * by a shutdown.
- */
-public fun CancellationException.assertShutdown() {
- if (this is ShutdownException) {
- throw this
- }
-}
-
-/**
- * This method terminates the current active coroutine if the specified [CancellationException] is caused
- * by a failure.
- */
-public fun CancellationException.assertFailure() {
- if (this is ShutdownException && cause != null) {
- throw this
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt
deleted file mode 100644
index 5b0035e3..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.atlarge.opendc.compute.core.image
-
-data class FlopsHistoryFragment(val tick: Long, val flops: Long, val duration: Long, val usage: Double, val cores: Int)
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt
deleted file mode 100644
index c615d865..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.atlarge.opendc.compute.core.image
-
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.TagContainer
-import java.util.UUID
-import kotlin.math.min
-
-class VmImage(
- public override val uid: UUID,
- public override val name: String,
- public override val tags: TagContainer,
- public val flopsHistory: Sequence<FlopsHistoryFragment>,
- public val maxCores: Int,
- public val requiredMemory: Long
-) : Image {
-
- override suspend fun invoke(ctx: ServerContext) {
- val clock = simulationContext.clock
- var offset = clock.millis()
-
- val batch = flopsHistory.map { fragment ->
- val cores = min(fragment.cores, ctx.server.flavor.cpuCount)
- val burst = LongArray(cores) { fragment.flops / cores }
- val usage = DoubleArray(cores) { fragment.usage / cores }
- offset += fragment.duration
- ServerContext.Slice(burst, usage, offset)
- }
-
- ctx.run(batch)
- }
-
- override fun toString(): String = "VmImage(uid=$uid, name=$name, cores=$maxCores, requiredMemory=$requiredMemory)"
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt
deleted file mode 100644
index 3f885f89..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.workload
-
-import com.atlarge.opendc.compute.core.Server
-import java.util.*
-import kotlin.random.Random
-
-/**
- * Meta-data key for the [PerformanceInterferenceModel] of an image.
- */
-const val IMAGE_PERF_INTERFERENCE_MODEL = "image:performance-interference"
-
-/**
- * Performance Interference Model describing the variability incurred by different sets of workloads if colocated.
- *
- * @param items The [PerformanceInterferenceModelItem]s that make up this model.
- */
-class PerformanceInterferenceModel(
- val items: SortedSet<PerformanceInterferenceModelItem>,
- val random: Random = Random(0)
-) {
- private var intersectingItems: List<PerformanceInterferenceModelItem> = emptyList()
- private val colocatedWorkloads = TreeMap<String, Int>()
-
- fun vmStarted(server: Server) {
- colocatedWorkloads.merge(server.image.name, 1, Int::plus)
- intersectingItems = items.filter { item -> doesMatch(item) }
- }
-
- fun vmStopped(server: Server) {
- colocatedWorkloads.computeIfPresent(server.image.name) { _, v -> (v - 1).takeUnless { it == 0 } }
- intersectingItems = items.filter { item -> doesMatch(item) }
- }
-
- private fun doesMatch(item: PerformanceInterferenceModelItem): Boolean {
- var count = 0
- for (name in item.workloadNames.subSet(colocatedWorkloads.firstKey(), colocatedWorkloads.lastKey() + "\u0000")) {
- count += colocatedWorkloads.getOrDefault(name, 0)
- if (count > 1)
- return true
- }
- return false
- }
-
- fun apply(currentServerLoad: Double): Double {
- if (intersectingItems.isEmpty()) {
- return 1.0
- }
- val score = intersectingItems
- .firstOrNull { it.minServerLoad <= currentServerLoad }
-
- // Apply performance penalty to (on average) only one of the VMs
- return if (score != null && random.nextInt(score.workloadNames.size) == 0) {
- score.performanceScore
- } else {
- 1.0
- }
- }
-}
-
-/**
- * Model describing how a specific set of workloads causes performance variability for each workload.
- *
- * @param workloadNames The names of the workloads that together cause performance variability for each workload in the set.
- * @param minServerLoad The minimum total server load at which this interference is activated and noticeable.
- * @param performanceScore The performance score that should be applied to each workload's performance. 1 means no
- * influence, <1 means that performance degrades, and >1 means that performance improves.
- */
-data class PerformanceInterferenceModelItem(
- val workloadNames: SortedSet<String>,
- val minServerLoad: Double,
- val performanceScore: Double
-) : Comparable<PerformanceInterferenceModelItem> {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as PerformanceInterferenceModelItem
-
- if (workloadNames != other.workloadNames) return false
-
- return true
- }
-
- override fun hashCode(): Int = workloadNames.hashCode()
-
- override fun compareTo(other: PerformanceInterferenceModelItem): Int {
- var cmp = performanceScore.compareTo(other.performanceScore)
- if (cmp != 0) {
- return cmp
- }
-
- cmp = minServerLoad.compareTo(other.minServerLoad)
- if (cmp != 0) {
- return cmp
- }
-
- return hashCode().compareTo(other.hashCode())
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt
deleted file mode 100644
index 098eb8ca..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.atlarge.opendc.compute.core.workload
-
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.core.workload.Workload
-import java.util.UUID
-
-/**
- * A workload that represents a VM.
- *
- * @property uid A unique identified of this VM.
- * @property name The name of this VM.
- * @property owner The owner of the VM.
- * @property image The image of the VM.
- */
-data class VmWorkload(
- override val uid: UUID,
- override val name: String,
- override val owner: User,
- val image: VmImage
-) : Workload {
- override fun equals(other: Any?): Boolean = other is VmWorkload && uid == other.uid
-
- override fun hashCode(): Int = uid.hashCode()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt
deleted file mode 100644
index a453e459..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.driver
-
-import com.atlarge.odcsim.Domain
-import com.atlarge.odcsim.SimulationContext
-import com.atlarge.odcsim.flow.EventFlow
-import com.atlarge.odcsim.flow.StateFlow
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.MemoryUnit
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.compute.core.execution.ServerManagementContext
-import com.atlarge.opendc.compute.core.execution.ShutdownException
-import com.atlarge.opendc.compute.core.image.EmptyImage
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.metal.NodeEvent
-import com.atlarge.opendc.compute.metal.NodeState
-import com.atlarge.opendc.compute.metal.power.ConstantPowerModel
-import com.atlarge.opendc.core.power.PowerModel
-import com.atlarge.opendc.core.services.ServiceKey
-import com.atlarge.opendc.core.services.ServiceRegistry
-import java.lang.Exception
-import java.time.Clock
-import java.util.UUID
-import kotlin.coroutines.ContinuationInterceptor
-import kotlin.math.ceil
-import kotlin.math.max
-import kotlin.math.min
-import kotlin.random.Random
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Delay
-import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.FlowPreview
-import kotlinx.coroutines.InternalCoroutinesApi
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.intrinsics.startCoroutineCancellable
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.selects.SelectClause0
-import kotlinx.coroutines.selects.SelectInstance
-import kotlinx.coroutines.withContext
-
-/**
- * A basic implementation of the [BareMetalDriver] that simulates an [Image] running on a bare-metal machine.
- *
- * @param domain The simulation domain the driver runs in.
- * @param uid The unique identifier of the machine.
- * @param name An optional name of the machine.
- * @param metadata The initial metadata of the node.
- * @param cpus The CPUs available to the bare metal machine.
- * @param memoryUnits The memory units in this machine.
- * @param powerModel The power model of this machine.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-public class SimpleBareMetalDriver(
- private val domain: Domain,
- uid: UUID,
- name: String,
- metadata: Map<String, Any>,
- val cpus: List<ProcessingUnit>,
- val memoryUnits: List<MemoryUnit>,
- powerModel: PowerModel<SimpleBareMetalDriver> = ConstantPowerModel(
- 0.0
- )
-) : BareMetalDriver {
- /**
- * The flavor that corresponds to this machine.
- */
- private val flavor = Flavor(cpus.size, memoryUnits.map { it.size }.sum())
-
- /**
- * The current active server context.
- */
- private var serverContext: BareMetalServerContext? = null
-
- /**
- * The events of the machine.
- */
- private val events = EventFlow<NodeEvent>()
-
- /**
- * The flow containing the load of the server.
- */
- private val usageState = MutableStateFlow(0.0)
-
- /**
- * The machine state.
- */
- private val nodeState = StateFlow(Node(uid, name, metadata + ("driver" to this), NodeState.SHUTOFF, EmptyImage, null, events))
-
- override val node: Flow<Node> = nodeState
-
- @OptIn(FlowPreview::class)
- override val usage: Flow<Double> = usageState
-
- override val powerDraw: Flow<Double> = powerModel(this)
-
- /**
- * The internal random instance.
- */
- private val random = Random(uid.leastSignificantBits xor uid.mostSignificantBits)
-
- override suspend fun init(): Node = withContext(domain.coroutineContext) {
- nodeState.value
- }
-
- override suspend fun start(): Node = withContext(domain.coroutineContext) {
- val node = nodeState.value
- if (node.state != NodeState.SHUTOFF) {
- return@withContext node
- }
-
- val events = EventFlow<ServerEvent>()
- val server = Server(
- UUID(random.nextLong(), random.nextLong()),
- node.name,
- emptyMap(),
- flavor,
- node.image,
- ServerState.BUILD,
- ServiceRegistry().put(BareMetalDriver, this@SimpleBareMetalDriver),
- events
- )
-
- setNode(node.copy(state = NodeState.BOOT, server = server))
- serverContext = BareMetalServerContext(events)
- return@withContext nodeState.value
- }
-
- override suspend fun stop(): Node = withContext(domain.coroutineContext) {
- val node = nodeState.value
- if (node.state == NodeState.SHUTOFF) {
- return@withContext node
- }
-
- // We terminate the image running on the machine
- serverContext!!.cancel(fail = false)
- serverContext = null
-
- setNode(node.copy(state = NodeState.SHUTOFF, server = null))
- return@withContext node
- }
-
- override suspend fun reboot(): Node = withContext(domain.coroutineContext) {
- stop()
- start()
- }
-
- override suspend fun setImage(image: Image): Node = withContext(domain.coroutineContext) {
- setNode(nodeState.value.copy(image = image))
- return@withContext nodeState.value
- }
-
- override suspend fun refresh(): Node = withContext(domain.coroutineContext) { nodeState.value }
-
- private fun setNode(value: Node) {
- val field = nodeState.value
- if (field.state != value.state) {
- events.emit(NodeEvent.StateChanged(value, field.state))
- }
-
- if (field.server != null && value.server != null && field.server.state != value.server.state) {
- serverContext!!.events.emit(ServerEvent.StateChanged(value.server, field.server.state))
- }
-
- nodeState.value = value
- }
-
- private inner class BareMetalServerContext(val events: EventFlow<ServerEvent>) : ServerManagementContext {
- private var finalized: Boolean = false
-
- // A state in which the machine is still available, but does not run any of the work requested by the
- // image
- var unavailable = false
-
- override val cpus: List<ProcessingUnit> = this@SimpleBareMetalDriver.cpus
-
- override val server: Server
- get() = nodeState.value.server!!
-
- private val job = domain.launch {
- delay(1) // TODO Introduce boot time
- init()
- try {
- server.image(this@BareMetalServerContext)
- exit()
- } catch (cause: Throwable) {
- exit(cause)
- }
- }
-
- /**
- * Cancel the image running on the machine.
- */
- suspend fun cancel(fail: Boolean) {
- if (fail)
- job.cancel(ShutdownException(cause = Exception("Random failure")))
- else
- job.cancel(ShutdownException())
- job.join()
- }
-
- override suspend fun <T : Any> publishService(key: ServiceKey<T>, service: T) {
- val server = server.copy(services = server.services.put(key, service))
- setNode(nodeState.value.copy(server = server))
- events.emit(ServerEvent.ServicePublished(server, key))
- }
-
- override suspend fun init() {
- assert(!finalized) { "Machine is already finalized" }
-
- val server = server.copy(state = ServerState.ACTIVE)
- setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
- }
-
- override suspend fun exit(cause: Throwable?) {
- finalized = true
-
- val newServerState =
- if (cause == null || (cause is ShutdownException && cause.cause == null))
- ServerState.SHUTOFF
- else
- ServerState.ERROR
- val newNodeState =
- if (cause == null || (cause is ShutdownException && cause.cause != null))
- nodeState.value.state
- else
- NodeState.ERROR
- val server = server.copy(state = newServerState)
- setNode(nodeState.value.copy(state = newNodeState, server = server))
- }
-
- /**
- * A disposable to prevent resetting the usage state for subsequent calls to onRun.
- */
- private var usageFlush: DisposableHandle? = null
-
- /**
- * Cache the [Clock] for timing.
- */
- private val clock = domain.coroutineContext[SimulationContext]!!.clock
-
- /**
- * Cache the [Delay] instance for timing.
- *
- * XXX We need to cache this before the call to [onRun] since doing this in [onRun] is too heavy.
- * XXX Note however that this is an ugly hack which may break in the future.
- */
- @OptIn(InternalCoroutinesApi::class)
- private val delay = domain.coroutineContext[ContinuationInterceptor] as Delay
-
- @OptIn(InternalCoroutinesApi::class)
- override fun onRun(
- batch: Sequence<ServerContext.Slice>,
- triggerMode: ServerContext.TriggerMode,
- merge: (ServerContext.Slice, ServerContext.Slice) -> ServerContext.Slice
- ): SelectClause0 {
- assert(!finalized) { "Server instance is already finalized" }
-
- return object : SelectClause0 {
- @InternalCoroutinesApi
- override fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R) {
- // Do not reset the usage state: we will set it ourselves
- usageFlush?.dispose()
- usageFlush = null
-
- val queue = batch.iterator()
- var start = Long.MIN_VALUE
- var currentWork: SliceWork? = null
- var currentDisposable: DisposableHandle? = null
-
- fun schedule(slice: ServerContext.Slice) {
- start = clock.millis()
-
- val isLastSlice = !queue.hasNext()
- val work = SliceWork(slice)
- val candidateDuration = when (triggerMode) {
- ServerContext.TriggerMode.FIRST -> work.minExit
- ServerContext.TriggerMode.LAST -> work.maxExit
- ServerContext.TriggerMode.DEADLINE -> slice.deadline - start
- }
-
- // Check whether the deadline is exceeded during the run of the slice.
- val duration = min(candidateDuration, slice.deadline - start)
-
- val action = Runnable {
- currentWork = null
-
- // Flush all the work that was performed
- val hasFinished = work.stop(duration)
-
- if (!isLastSlice) {
- val candidateSlice = queue.next()
- val nextSlice =
- // If our previous slice exceeds its deadline, merge it with the next candidate slice
- if (hasFinished)
- candidateSlice
- else
- merge(candidateSlice, slice)
- schedule(nextSlice)
- } else if (select.trySelect()) {
- block.startCoroutineCancellable(select.completion)
- }
- }
-
- // Schedule the flush after the entire slice has finished
- currentDisposable = delay.invokeOnTimeout(duration, action)
-
- // Start the slice work
- currentWork = work
- work.start()
- }
-
- // Schedule the first work
- if (queue.hasNext()) {
- schedule(queue.next())
-
- // A DisposableHandle to flush the work in case the call is cancelled
- val disposable = DisposableHandle {
- val end = clock.millis()
- val duration = end - start
-
- currentWork?.stop(duration)
- currentDisposable?.dispose()
-
- // Schedule reset the usage of the machine since the call is returning
- usageFlush = delay.invokeOnTimeout(1, Runnable {
- usageState.value = 0.0
- usageFlush = null
- })
- }
-
- select.disposeOnSelect(disposable)
- } else if (select.trySelect()) {
- // No work has been given: select immediately
- block.startCoroutineCancellable(select.completion)
- }
- }
- }
- }
-
- /**
- * A slice to be processed.
- */
- private inner class SliceWork(val slice: ServerContext.Slice) {
- /**
- * The duration after which the first processor finishes processing this slice.
- */
- public val minExit: Long
-
- /**
- * The duration after which the last processor finishes processing this slice.
- */
- public val maxExit: Long
-
- /**
- * A flag to indicate that the slice will exceed the deadline.
- */
- public val exceedsDeadline: Boolean
- get() = slice.deadline < maxExit
-
- /**
- * The total amount of CPU usage.
- */
- public val totalUsage: Double
-
- /**
- * A flag to indicate that this slice is empty.
- */
- public val isEmpty: Boolean
-
- init {
- var totalUsage = 0.0
- var minExit = Long.MAX_VALUE
- var maxExit = 0L
- var nonEmpty = false
-
- // Determine the duration of the first/last CPU to finish
- for (i in 0 until min(cpus.size, slice.burst.size)) {
- val cpu = cpus[i]
- val usage = min(slice.limit[i], cpu.frequency)
- val cpuDuration = ceil(slice.burst[i] / usage * 1000).toLong() // Convert from seconds to milliseconds
-
- totalUsage += usage / cpu.frequency
-
- if (cpuDuration != 0L) { // We only wait for processor cores with a non-zero burst
- minExit = min(minExit, cpuDuration)
- maxExit = max(maxExit, cpuDuration)
- nonEmpty = true
- }
- }
-
- this.isEmpty = !nonEmpty
- this.totalUsage = totalUsage
- this.minExit = minExit
- this.maxExit = maxExit
- }
-
- /**
- * Indicate that the work on the slice has started.
- */
- public fun start() {
- usageState.value = totalUsage / cpus.size
- }
-
- /**
- * Flush the work performed on the slice.
- */
- public fun stop(duration: Long): Boolean {
- var hasFinished = true
-
- // Only flush the work if the machine is available
- if (!unavailable) {
- for (i in 0 until min(cpus.size, slice.burst.size)) {
- val usage = min(slice.limit[i], cpus[i].frequency)
- val granted = ceil(duration / 1000.0 * usage).toLong()
- val res = max(0, slice.burst[i] - granted)
- slice.burst[i] = res
-
- if (res != 0L) {
- hasFinished = false
- }
- }
- }
-
- return hasFinished
- }
- }
- }
-
- override val scope: CoroutineScope
- get() = domain
-
- override suspend fun fail() {
- serverContext?.unavailable = true
-
- val server = nodeState.value.server?.copy(state = ServerState.ERROR)
- setNode(nodeState.value.copy(state = NodeState.ERROR, server = server))
- }
-
- override suspend fun recover() {
- serverContext?.unavailable = false
-
- val server = nodeState.value.server?.copy(state = ServerState.ACTIVE)
- setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
- }
-
- override fun toString(): String = "SimpleBareMetalDriver(node = ${nodeState.value.uid})"
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt
deleted file mode 100644
index 607759a8..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt
-
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.virt.driver.SimpleVirtDriver
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.core.resource.TagContainer
-import java.util.UUID
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.suspendCancellableCoroutine
-
-/**
- * A hypervisor managing the VMs of a node.
- */
-object HypervisorImage : Image {
- override val uid: UUID = UUID.randomUUID()
- override val name: String = "vmm"
- override val tags: TagContainer = emptyMap()
-
- override suspend fun invoke(ctx: ServerContext) {
- coroutineScope {
- val driver = SimpleVirtDriver(ctx, this)
- ctx.publishService(VirtDriver.Key, driver)
-
- // Suspend image until it is cancelled
- try {
- suspendCancellableCoroutine<Unit> {}
- } finally {
- driver.cancel()
- }
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt
deleted file mode 100644
index e52a1698..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.atlarge.opendc.compute.virt.service
-
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import java.util.UUID
-
-class HypervisorView(
- val uid: UUID,
- var server: Server,
- var numberOfActiveServers: Int,
- var availableMemory: Long,
- var provisionedCores: Int
-) {
- lateinit var driver: VirtDriver
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt
deleted file mode 100644
index 79388bc3..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt
+++ /dev/null
@@ -1,351 +0,0 @@
-package com.atlarge.opendc.compute.virt.service
-
-import com.atlarge.odcsim.SimulationContext
-import com.atlarge.odcsim.flow.EventFlow
-import com.atlarge.odcsim.simulationContext
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.compute.virt.HypervisorEvent
-import com.atlarge.opendc.compute.virt.HypervisorImage
-import com.atlarge.opendc.compute.virt.driver.InsufficientMemoryOnServerException
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.compute.virt.service.allocation.AllocationPolicy
-import com.atlarge.opendc.core.services.ServiceKey
-import kotlin.coroutines.Continuation
-import kotlin.coroutines.resume
-import kotlin.math.max
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.suspendCancellableCoroutine
-import kotlinx.coroutines.withContext
-import mu.KotlinLogging
-
-private val logger = KotlinLogging.logger {}
-
-@OptIn(ExperimentalCoroutinesApi::class)
-class SimpleVirtProvisioningService(
- public override val allocationPolicy: AllocationPolicy,
- private val ctx: SimulationContext,
- private val provisioningService: ProvisioningService
-) : VirtProvisioningService, CoroutineScope by ctx.domain {
- /**
- * The hypervisors that have been launched by the service.
- */
- private val hypervisors: MutableMap<Server, HypervisorView> = mutableMapOf()
-
- /**
- * The available hypervisors.
- */
- private val availableHypervisors: MutableSet<HypervisorView> = mutableSetOf()
-
- /**
- * The incoming images to be processed by the provisioner.
- */
- private val incomingImages: MutableSet<ImageView> = mutableSetOf()
-
- /**
- * The active images in the system.
- */
- private val activeImages: MutableSet<ImageView> = mutableSetOf()
-
- public var submittedVms = 0
- public var queuedVms = 0
- public var runningVms = 0
- public var finishedVms = 0
- public var unscheduledVms = 0
-
- private var maxCores = 0
- private var maxMemory = 0L
-
- /**
- * The allocation logic to use.
- */
- private val allocationLogic = allocationPolicy()
-
- /**
- * The [EventFlow] to emit the events.
- */
- internal val eventFlow = EventFlow<VirtProvisioningEvent>()
-
- override val events: Flow<VirtProvisioningEvent> = eventFlow
-
- init {
- launch {
- val provisionedNodes = provisioningService.nodes()
- provisionedNodes.forEach { node ->
- val hypervisorImage = HypervisorImage
- val node = provisioningService.deploy(node, hypervisorImage)
- node.server!!.events.onEach { event ->
- when (event) {
- is ServerEvent.StateChanged -> stateChanged(event.server)
- is ServerEvent.ServicePublished -> servicePublished(event.server, event.key)
- }
- }.launchIn(this)
- }
- }
- }
-
- override suspend fun drivers(): Set<VirtDriver> = withContext(coroutineContext) {
- availableHypervisors.map { it.driver }.toSet()
- }
-
- override suspend fun deploy(
- name: String,
- image: Image,
- flavor: Flavor
- ): Server = withContext(coroutineContext) {
- eventFlow.emit(VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- ++submittedVms,
- runningVms,
- finishedVms,
- ++queuedVms,
- unscheduledVms
- ))
-
- suspendCancellableCoroutine<Server> { cont ->
- val vmInstance = ImageView(name, image, flavor, cont)
- incomingImages += vmInstance
- requestCycle()
- }
- }
-
- override suspend fun terminate() {
- val provisionedNodes = provisioningService.nodes()
- provisionedNodes.forEach { node -> provisioningService.stop(node) }
- }
-
- private var call: Job? = null
-
- private fun requestCycle() {
- if (call != null) {
- return
- }
-
- val quantum = 300000 // 5 minutes in milliseconds
- // We assume that the provisioner runs at a fixed slot every time quantum (e.g t=0, t=60, t=120).
- // This is important because the slices of the VMs need to be aligned.
- // We calculate here the delay until the next scheduling slot.
- val delay = quantum - (ctx.clock.millis() % quantum)
-
- val call = launch {
- delay(delay)
- this@SimpleVirtProvisioningService.call = null
- schedule()
- }
- this.call = call
- }
-
- private suspend fun schedule() {
- val clock = simulationContext.clock
- val imagesToBeScheduled = incomingImages.toSet()
-
- for (imageInstance in imagesToBeScheduled) {
- val requiredMemory = (imageInstance.image as VmImage).requiredMemory
- val selectedHv = allocationLogic.select(availableHypervisors, imageInstance)
-
- if (selectedHv == null) {
- if (requiredMemory > maxMemory || imageInstance.flavor.cpuCount > maxCores) {
- eventFlow.emit(VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- ++unscheduledVms
- ))
-
- incomingImages -= imageInstance
-
- logger.warn("Failed to spawn ${imageInstance.image}: does not fit [${clock.millis()}]")
- continue
- } else {
- break
- }
- }
-
- try {
- logger.info { "[${ctx.clock.millis()}] Spawning ${imageInstance.image} on ${selectedHv.server.uid} ${selectedHv.server.name} ${selectedHv.server.flavor}" }
- incomingImages -= imageInstance
-
- // Speculatively update the hypervisor view information to prevent other images in the queue from
- // deciding on stale values.
- selectedHv.numberOfActiveServers++
- selectedHv.provisionedCores += imageInstance.flavor.cpuCount
- selectedHv.availableMemory -= requiredMemory // XXX Temporary hack
-
- val server = selectedHv.driver.spawn(
- imageInstance.name,
- imageInstance.image,
- imageInstance.flavor
- )
- imageInstance.server = server
- imageInstance.continuation.resume(server)
-
- eventFlow.emit(VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- ++runningVms,
- finishedVms,
- --queuedVms,
- unscheduledVms
- ))
- activeImages += imageInstance
-
- server.events
- .onEach { event ->
- when (event) {
- is ServerEvent.StateChanged -> {
- if (event.server.state == ServerState.SHUTOFF) {
- logger.info { "[${ctx.clock.millis()}] Server ${event.server.uid} ${event.server.name} ${event.server.flavor} finished." }
-
- eventFlow.emit(VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- --runningVms,
- ++finishedVms,
- queuedVms,
- unscheduledVms
- ))
-
- activeImages -= imageInstance
- selectedHv.provisionedCores -= server.flavor.cpuCount
-
- // Try to reschedule if needed
- if (incomingImages.isNotEmpty()) {
- requestCycle()
- }
- }
- }
- }
- }
- .launchIn(this)
- } catch (e: InsufficientMemoryOnServerException) {
- logger.error("Failed to deploy VM", e)
-
- selectedHv.numberOfActiveServers--
- selectedHv.provisionedCores -= imageInstance.flavor.cpuCount
- selectedHv.availableMemory += requiredMemory
- } catch (e: Throwable) {
- logger.error("Failed to deploy VM", e)
- }
- }
- }
-
- private fun stateChanged(server: Server) {
- when (server.state) {
- ServerState.ACTIVE -> {
- logger.debug { "[${ctx.clock.millis()}] Server ${server.uid} available: ${server.state}" }
-
- if (server in hypervisors) {
- // Corner case for when the hypervisor already exists
- availableHypervisors += hypervisors.getValue(server)
- } else {
- val hv = HypervisorView(
- server.uid,
- server,
- 0,
- server.flavor.memorySize,
- 0
- )
- maxCores = max(maxCores, server.flavor.cpuCount)
- maxMemory = max(maxMemory, server.flavor.memorySize)
- hypervisors[server] = hv
- }
-
- eventFlow.emit(VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- unscheduledVms
- ))
-
- // Re-schedule on the new machine
- if (incomingImages.isNotEmpty()) {
- requestCycle()
- }
- }
- ServerState.SHUTOFF, ServerState.ERROR -> {
- logger.debug { "[${ctx.clock.millis()}] Server ${server.uid} unavailable: ${server.state}" }
- val hv = hypervisors[server] ?: return
- availableHypervisors -= hv
-
- eventFlow.emit(VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- unscheduledVms
- ))
-
- if (incomingImages.isNotEmpty()) {
- requestCycle()
- }
- }
- else -> throw IllegalStateException()
- }
- }
-
- private fun servicePublished(server: Server, key: ServiceKey<*>) {
- if (key == VirtDriver.Key) {
- val hv = hypervisors[server] ?: return
- hv.driver = server.services[VirtDriver]
- availableHypervisors += hv
-
- eventFlow.emit(VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- unscheduledVms
- ))
-
- hv.driver.events
- .onEach { event ->
- if (event is HypervisorEvent.VmsUpdated) {
- hv.numberOfActiveServers = event.numberOfActiveServers
- hv.availableMemory = event.availableMemory
- }
- }.launchIn(this)
-
- requestCycle()
- }
- }
-
- data class ImageView(
- val name: String,
- val image: Image,
- val flavor: Flavor,
- val continuation: Continuation<Server>,
- var server: Server? = null
- )
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt
deleted file mode 100644
index c4cbd711..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.atlarge.opendc.compute.virt.service
-
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.compute.virt.service.allocation.AllocationPolicy
-import kotlinx.coroutines.flow.Flow
-
-/**
- * A service for VM provisioning on a cloud.
- */
-interface VirtProvisioningService {
- /**
- * The policy used for allocating a VM on the available hypervisors.
- */
- val allocationPolicy: AllocationPolicy
-
- /**
- * The events emitted by the service.
- */
- public val events: Flow<VirtProvisioningEvent>
-
- /**
- * Obtain the active hypervisors for this provisioner.
- */
- public suspend fun drivers(): Set<VirtDriver>
-
- /**
- * Submit the specified [Image] to the provisioning service.
- *
- * @param name The name of the server to deploy.
- * @param image The image to be deployed.
- * @param flavor The flavor of the machine instance to run this [image] on.
- */
- public suspend fun deploy(name: String, image: Image, flavor: Flavor): Server
-
- /**
- * Terminate the provisioning service releasing all the leased bare-metal machines.
- */
- public suspend fun terminate()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt
deleted file mode 100644
index b7c9388d..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-
-/**
- * A policy for selecting the [Node] an image should be deployed to,
- */
-public interface AllocationPolicy {
- /**
- * The logic of the allocation policy.
- */
- public interface Logic {
- /**
- * Select the node on which the server should be scheduled.
- */
- public fun select(hypervisors: Set<HypervisorView>, image: SimpleVirtProvisioningService.ImageView): HypervisorView?
- }
-
- /**
- * Builds the logic of the policy.
- */
- operator fun invoke(): Logic
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt
deleted file mode 100644
index c081244f..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-
-/**
- * Allocation policy that selects the node with the most available memory.
- *
- * @param reversed A flag to reverse the order (least amount of memory scores the best).
- */
-public class AvailableMemoryAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
- override val comparator: Comparator<HypervisorView> = compareBy<HypervisorView> { -it.availableMemory }
- .run { if (reversed) reversed() else this }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt
deleted file mode 100644
index 7e3e5864..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-
-/**
- * Allocation policy that selects the node with the least amount of active servers.
- *
- * @param reversed A flag to reverse the order, such that the node with the most active servers is selected.
- */
-public class NumberOfActiveServersAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
- override val comparator: Comparator<HypervisorView> = compareBy<HypervisorView> { it.numberOfActiveServers }
- .run { if (reversed) reversed() else this }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt
deleted file mode 100644
index 59acfce2..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-import mu.KotlinLogging
-
-private val logger = KotlinLogging.logger {}
-
-/**
- * Policy replaying VM-cluster assignment.
- *
- * Within each cluster, the active servers on each node determine which node gets
- * assigned the VM image.
- */
-class ReplayAllocationPolicy(val vmPlacements: Map<String, String>) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : AllocationPolicy.Logic {
- override fun select(
- hypervisors: Set<HypervisorView>,
- image: SimpleVirtProvisioningService.ImageView
- ): HypervisorView? {
- val clusterName = vmPlacements[image.name]
- ?: throw IllegalStateException("Could not find placement data in VM placement file for VM ${image.name}")
- val machinesInCluster = hypervisors.filter { it.server.name.contains(clusterName) }
-
- if (machinesInCluster.isEmpty()) {
- logger.info { "Could not find any machines belonging to cluster $clusterName for image ${image.name}, assigning randomly." }
- return hypervisors.maxBy { it.availableMemory }
- }
-
- return machinesInCluster.maxBy { it.availableMemory }
- ?: throw IllegalStateException("Cloud not find any machine and could not randomly assign")
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt b/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt
deleted file mode 100644
index 622b185e..00000000
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt
-
-import com.atlarge.odcsim.SimulationEngineProvider
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
-import com.atlarge.opendc.compute.core.image.FlopsHistoryFragment
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import java.util.ServiceLoader
-import java.util.UUID
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Disabled
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertAll
-
-/**
- * Basic test-suite for the hypervisor.
- */
-internal class HypervisorTest {
- /**
- * A smoke test for the bare-metal driver.
- */
- @OptIn(ExperimentalCoroutinesApi::class)
- @Test
- @Disabled
- fun smoke() {
- val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
- val system = provider("test")
- val root = system.newDomain("root")
-
- root.launch {
- val vmm = HypervisorImage
- val workloadA = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1_000, 1)
- val workloadB = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 2_000, 1)
-
- val driverDom = root.newDomain("driver")
-
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1)
- val cpus = List(1) { ProcessingUnit(cpuNode, it, 2000.0) }
- val metalDriver = SimpleBareMetalDriver(driverDom, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
-
- metalDriver.init()
- metalDriver.setImage(vmm)
- val node = metalDriver.start()
- node.server?.events?.onEach { println(it) }?.launchIn(this)
-
- delay(5)
-
- val flavor = Flavor(1, 0)
- val vmDriver = metalDriver.refresh().server!!.services[VirtDriver]
- vmDriver.events.onEach { println(it) }.launchIn(this)
- val vmA = vmDriver.spawn("a", workloadA, flavor)
- vmA.events.onEach { println(it) }.launchIn(this)
- val vmB = vmDriver.spawn("b", workloadB, flavor)
- vmB.events.onEach { println(it) }.launchIn(this)
- }
-
- runBlocking {
- system.run()
- system.terminate()
- }
- }
-
- /**
- * Test overcommissioning of a hypervisor.
- */
- @Test
- fun overcommission() {
- val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
- val system = provider("test")
- val root = system.newDomain("root")
-
- var requestedBurst = 0L
- var grantedBurst = 0L
- var overcommissionedBurst = 0L
-
- root.launch {
- val vmm = HypervisorImage
- val duration = 5 * 60L
- val vmImageA = VmImage(UUID.randomUUID(), "<unnamed>", emptyMap(), sequenceOf(
- FlopsHistoryFragment(0, 28L * duration, duration * 1000, 28.0, 2),
- FlopsHistoryFragment(0, 3500L * duration, duration * 1000, 3500.0, 2),
- FlopsHistoryFragment(0, 0, duration * 1000, 0.0, 2),
- FlopsHistoryFragment(0, 183L * duration, duration * 1000, 183.0, 2)
- ), 2, 0)
- val vmImageB = VmImage(UUID.randomUUID(), "<unnamed>", emptyMap(), sequenceOf(
- FlopsHistoryFragment(0, 28L * duration, duration * 1000, 28.0, 2),
- FlopsHistoryFragment(0, 3100L * duration, duration * 1000, 3100.0, 2),
- FlopsHistoryFragment(0, 0, duration * 1000, 0.0, 2),
- FlopsHistoryFragment(0, 73L * duration, duration * 1000, 73.0, 2)
- ), 2, 0)
-
- val driverDom = root.newDomain("driver")
-
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
- val cpus = List(2) { ProcessingUnit(cpuNode, it, 3200.0) }
- val metalDriver = SimpleBareMetalDriver(driverDom, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
-
- metalDriver.init()
- metalDriver.setImage(vmm)
- metalDriver.start()
-
- delay(5)
-
- val flavor = Flavor(2, 0)
- val vmDriver = metalDriver.refresh().server!!.services[VirtDriver]
- vmDriver.events
- .onEach { event ->
- when (event) {
- is HypervisorEvent.SliceFinished -> {
- requestedBurst += event.requestedBurst
- grantedBurst += event.grantedBurst
- overcommissionedBurst += event.overcommissionedBurst
- }
- }
- }
- .launchIn(this)
-
- vmDriver.spawn("a", vmImageA, flavor)
- vmDriver.spawn("b", vmImageB, flavor)
- }
-
- runBlocking {
- system.run()
- system.terminate()
- }
-
- assertAll(
- { assertEquals(2073600, requestedBurst, "Requested Burst does not match") },
- { assertEquals(2013600, grantedBurst, "Granted Burst does not match") },
- { assertEquals(60000, overcommissionedBurst, "Overcommissioned Burst does not match") }
- )
- }
-}
diff --git a/simulator/opendc/opendc-format/src/test/kotlin/com/atlarge/opendc/format/trace/swf/SwfTraceReaderTest.kt b/simulator/opendc/opendc-format/src/test/kotlin/com/atlarge/opendc/format/trace/swf/SwfTraceReaderTest.kt
deleted file mode 100644
index 94e4b0fc..00000000
--- a/simulator/opendc/opendc-format/src/test/kotlin/com/atlarge/opendc/format/trace/swf/SwfTraceReaderTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.atlarge.opendc.format.trace.swf
-
-import java.io.File
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-
-class SwfTraceReaderTest {
- @Test
- internal fun testParseSwf() {
- val reader = SwfTraceReader(File(SwfTraceReaderTest::class.java.getResource("/swf_trace.txt").toURI()))
- var entry = reader.next()
- assertEquals(0, entry.submissionTime)
- // 1961 slices for waiting, 3 full and 1 partial running slices
- assertEquals(1965, entry.workload.image.flopsHistory.toList().size)
-
- entry = reader.next()
- assertEquals(164472, entry.submissionTime)
- // 1188 slices for waiting, 0 full and 1 partial running slices
- assertEquals(1189, entry.workload.image.flopsHistory.toList().size)
- assertEquals(5_100_000L, entry.workload.image.flopsHistory.toList().last().flops)
- assertEquals(0.25, entry.workload.image.flopsHistory.toList().last().usage)
- }
-}
diff --git a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowSchedulerListener.kt b/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowSchedulerListener.kt
deleted file mode 100644
index 73c3e752..00000000
--- a/simulator/opendc/opendc-workflows/src/main/kotlin/com/atlarge/opendc/workflows/service/StageWorkflowSchedulerListener.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.workflows.service
-
-interface StageWorkflowSchedulerListener {
- fun cycleStarted(scheduler: StageWorkflowService) {}
- fun cycleFinished(scheduler: StageWorkflowService) {}
-
- fun jobSubmitted(job: JobState) {}
- fun jobStarted(job: JobState) {}
- fun jobFinished(job: JobState) {}
-
- fun taskReady(task: TaskState) {}
- fun taskAssigned(task: TaskState) {}
- fun taskStarted(task: TaskState) {}
- fun taskFinished(task: TaskState) {}
-}
diff --git a/simulator/settings.gradle.kts b/simulator/settings.gradle.kts
index 9411d882..935a18d0 100644
--- a/simulator/settings.gradle.kts
+++ b/simulator/settings.gradle.kts
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2017 atlarge-research
+ * Copyright (c) 2017 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,12 +21,15 @@
*/
rootProject.name = "opendc-simulator"
-include(":odcsim:odcsim-api")
-include(":odcsim:odcsim-engine-omega")
-include(":opendc:opendc-core")
-include(":opendc:opendc-compute")
-include(":opendc:opendc-format")
-include(":opendc:opendc-workflows")
-include(":opendc:opendc-experiments-sc18")
-include(":opendc:opendc-experiments-sc20")
-include(":opendc:opendc-runner-web")
+include(":opendc-core")
+include(":opendc-compute:opendc-compute-core")
+include(":opendc-compute:opendc-compute-simulator")
+include(":opendc-workflows")
+include(":opendc-format")
+include(":opendc-experiments:opendc-experiments-sc18")
+include(":opendc-experiments:opendc-experiments-sc20")
+include(":opendc-runner-web")
+include(":opendc-simulator:opendc-simulator-core")
+include(":opendc-simulator:opendc-simulator-compute")
+include(":opendc-simulator:opendc-simulator-failures")
+include(":opendc-utils")