summaryrefslogtreecommitdiff
path: root/simulator
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-03-08 22:19:37 +0100
committerFabian Mastenbroek <mail.fabianm@gmail.com>2021-03-08 22:19:37 +0100
commite97774dbf274fcb57b9d173f9d674a2ef1b982af (patch)
tree7d98f62a230ca33d32e71e8bed045874f97a9619 /simulator
parent75751865179c6cd5a05abb4a0641193595f59b45 (diff)
compute: Remove use of bare-metal provisioning from compute module
This change removes the usage of bare-metal provisioning from the OpenDC Compute module. This significantly simplifies the experiment setup.
Diffstat (limited to 'simulator')
-rw-r--r--simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt5
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts1
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt188
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt103
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHostProvisioner.kt69
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt8
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimBareMetalDriverTest.kt92
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt18
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimProvisioningServiceTest.kt81
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt22
-rw-r--r--simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt97
-rw-r--r--simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt9
-rw-r--r--simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMonitor.kt13
-rw-r--r--simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ParquetExperimentMonitor.kt24
-rw-r--r--simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/HostEvent.kt4
-rw-r--r--simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/parquet/ParquetHostEventWriter.kt4
-rw-r--r--simulator/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt18
-rw-r--r--simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/UnderspecificationExperiment.kt28
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt6
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/MachineDef.kt (renamed from simulator/opendc-metal/src/main/kotlin/org/opendc/metal/Metadata.kt)23
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt45
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt39
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt42
-rw-r--r--simulator/opendc-metal/build.gradle.kts38
-rw-r--r--simulator/opendc-metal/src/main/kotlin/org/opendc/metal/Node.kt72
-rw-r--r--simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeEvent.kt41
-rw-r--r--simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeState.kt55
-rw-r--r--simulator/opendc-metal/src/main/kotlin/org/opendc/metal/driver/BareMetalDriver.kt84
-rw-r--r--simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/ProvisioningService.kt64
-rw-r--r--simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/SimpleProvisioningService.kt65
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt13
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt45
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/WebExperimentMonitor.kt37
-rw-r--r--simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt33
-rw-r--r--simulator/settings.gradle.kts1
35 files changed, 253 insertions, 1234 deletions
diff --git a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt
index 2cd91144..060c35fd 100644
--- a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt
+++ b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt
@@ -51,6 +51,11 @@ public interface Host {
public val state: HostState
/**
+ * Meta-data associated with the host.
+ */
+ public val meta: Map<String, Any>
+
+ /**
* The events emitted by the driver.
*/
public val events: Flow<HostEvent>
diff --git a/simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts b/simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts
index d7d5f002..31fcda2f 100644
--- a/simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts
+++ b/simulator/opendc-compute/opendc-compute-simulator/build.gradle.kts
@@ -31,7 +31,6 @@ plugins {
dependencies {
api(platform(project(":opendc-platform")))
api(project(":opendc-compute:opendc-compute-service"))
- api(project(":opendc-metal"))
api(project(":opendc-simulator:opendc-simulator-compute"))
api(project(":opendc-simulator:opendc-simulator-failures"))
implementation(project(":opendc-utils"))
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
deleted file mode 100644
index 2405a8f9..00000000
--- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.api.Flavor
-import org.opendc.compute.api.Image
-import org.opendc.compute.simulator.power.api.CpuPowerModel
-import org.opendc.compute.simulator.power.api.Powerable
-import org.opendc.compute.simulator.power.models.ConstantPowerModel
-import org.opendc.metal.Node
-import org.opendc.metal.NodeEvent
-import org.opendc.metal.NodeState
-import org.opendc.metal.driver.BareMetalDriver
-import org.opendc.simulator.compute.SimBareMetalMachine
-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
-
-/**
- * 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 cpuPowerModel The CPU 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,
- cpuPowerModel: CpuPowerModel = 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, flavor, Image.EMPTY, 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> = cpuPowerModel.getPowerDraw(this)
-
- /**
- * The [Job] that runs the simulated workload.
- */
- private var job: Job? = 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 workload = node.image.tags["workload"] as SimWorkload
-
- job = coroutineScope.launch {
- delay(1) // TODO Introduce boot time
- initMachine()
- try {
- machine.run(workload, mapOf("driver" to this@SimBareMetalDriver, "node" to node))
- exitMachine(null)
- } catch (_: CancellationException) {
- // Ignored
- } catch (cause: Throwable) {
- exitMachine(cause)
- }
- }
-
- setNode(node.copy(state = NodeState.BOOT))
- return nodeState.value
- }
-
- private fun initMachine() {
- setNode(nodeState.value.copy(state = NodeState.ACTIVE))
- }
-
- private fun exitMachine(cause: Throwable?) {
- val newNodeState =
- if (cause == null)
- NodeState.SHUTOFF
- else
- NodeState.ERROR
- setNode(nodeState.value.copy(state = newNodeState))
- }
-
- override suspend fun stop(): Node {
- val node = nodeState.value
- if (node.state == NodeState.SHUTOFF) {
- return node
- }
-
- job?.cancelAndJoin()
- setNode(node.copy(state = NodeState.SHUTOFF))
- 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))
- }
-
- nodeState.value = value
- }
-
- override val scope: CoroutineScope
- get() = coroutineScope
-
- override suspend fun fail() {
- setNode(nodeState.value.copy(state = NodeState.ERROR))
- }
-
- override suspend fun recover() {
- setNode(nodeState.value.copy(state = NodeState.ACTIVE))
- }
-
- 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/SimHost.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
index fd547d3d..e2d70dce 100644
--- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
@@ -29,34 +29,43 @@ import org.opendc.compute.api.Flavor
import org.opendc.compute.api.Server
import org.opendc.compute.api.ServerState
import org.opendc.compute.service.driver.*
-import org.opendc.metal.Node
+import org.opendc.compute.simulator.power.api.CpuPowerModel
+import org.opendc.compute.simulator.power.api.Powerable
+import org.opendc.compute.simulator.power.models.ConstantPowerModel
import org.opendc.simulator.compute.*
import org.opendc.simulator.compute.interference.IMAGE_PERF_INTERFERENCE_MODEL
import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
import org.opendc.simulator.compute.model.MemoryUnit
-import org.opendc.simulator.compute.workload.SimResourceCommand
import org.opendc.simulator.compute.workload.SimWorkload
+import org.opendc.simulator.failures.FailureDomain
import org.opendc.utils.flow.EventFlow
+import java.time.Clock
import java.util.*
+import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
/**
* A [Host] that is simulates virtual machines on a physical machine using [SimHypervisor].
*/
public class SimHost(
- public val node: Node,
- private val coroutineScope: CoroutineScope,
- hypervisor: SimHypervisorProvider
-) : Host, SimWorkload {
+ override val uid: UUID,
+ override val name: String,
+ model: SimMachineModel,
+ override val meta: Map<String, Any>,
+ context: CoroutineContext,
+ clock: Clock,
+ hypervisor: SimHypervisorProvider,
+ cpuPowerModel: CpuPowerModel = ConstantPowerModel(0.0),
+) : Host, FailureDomain, Powerable, AutoCloseable {
/**
- * The logger instance of this server.
+ * The [CoroutineScope] of the host bounded by the lifecycle of the host.
*/
- private val logger = KotlinLogging.logger {}
+ override val scope: CoroutineScope = CoroutineScope(context)
/**
- * The execution context in which the [Host] runs.
+ * The logger instance of this server.
*/
- private lateinit var ctx: SimExecutionContext
+ private val logger = KotlinLogging.logger {}
override val events: Flow<HostEvent>
get() = _events
@@ -70,12 +79,17 @@ public class SimHost(
/**
* Current total memory use of the images on this hypervisor.
*/
- private var availableMemory: Long = 0
+ private var availableMemory: Long = model.memory.map { it.size }.sum()
+
+ /**
+ * The machine to run on.
+ */
+ public val machine: SimBareMetalMachine = SimBareMetalMachine(scope, clock, model)
/**
* The hypervisor to run multiple workloads.
*/
- private val hypervisor = hypervisor.create(
+ public val hypervisor: SimHypervisor = hypervisor.create(
object : SimHypervisor.Listener {
override fun onSliceFinish(
hypervisor: SimHypervisor,
@@ -107,26 +121,38 @@ public class SimHost(
*/
private val guests = HashMap<Server, Guest>()
- override val uid: UUID
- get() = node.uid
-
- override val name: String
- get() = node.name
-
- override val model: HostModel
- get() = HostModel(node.flavor.cpuCount, node.flavor.memorySize)
-
override val state: HostState
get() = _state
- private var _state: HostState = HostState.UP
+ private var _state: HostState = HostState.DOWN
set(value) {
listeners.forEach { it.onStateChanged(this, value) }
field = value
}
+ override val model: HostModel = HostModel(model.cpus.size, model.memory.map { it.size }.sum())
+
+ override val powerDraw: Flow<Double> = cpuPowerModel.getPowerDraw(this)
+
+ init {
+ // Launch hypervisor onto machine
+ scope.launch {
+ try {
+ _state = HostState.UP
+ machine.run(this@SimHost.hypervisor, emptyMap())
+ } catch (_: CancellationException) {
+ // Ignored
+ } catch (cause: Throwable) {
+ logger.error(cause) { "Host failed" }
+ throw cause
+ } finally {
+ _state = HostState.DOWN
+ }
+ }
+ }
+
override fun canFit(server: Server): Boolean {
val sufficientMemory = availableMemory > server.flavor.memorySize
- val enoughCpus = ctx.machine.cpus.size >= server.flavor.cpuCount
+ val enoughCpus = machine.model.cpus.size >= server.flavor.cpuCount
val canFit = hypervisor.canFit(server.flavor.toMachineModel())
return sufficientMemory && enoughCpus && canFit
@@ -176,11 +202,16 @@ public class SimHost(
listeners.remove(listener)
}
+ override fun close() {
+ scope.cancel()
+ _state = HostState.DOWN
+ }
+
/**
* Convert flavor to machine model.
*/
private fun Flavor.toMachineModel(): SimMachineModel {
- val originalCpu = ctx.machine.cpus[0]
+ val originalCpu = machine.model.cpus[0]
val processingNode = originalCpu.node.copy(coreCount = cpuCount)
val processingUnits = (0 until cpuCount).map { originalCpu.copy(id = it, node = processingNode) }
val memoryUnits = listOf(MemoryUnit("Generic", "Generic", 3200.0, memorySize))
@@ -210,6 +241,14 @@ public class SimHost(
_events.emit(HostEvent.VmsUpdated(this@SimHost, guests.count { it.value.state == ServerState.ACTIVE }, availableMemory))
}
+ override suspend fun fail() {
+ _state = HostState.DOWN
+ }
+
+ override suspend fun recover() {
+ _state = HostState.UP
+ }
+
/**
* A virtual machine instance that the driver manages.
*/
@@ -251,7 +290,7 @@ public class SimHost(
assert(job == null) { "Concurrent job running" }
val workload = server.image.tags["workload"] as SimWorkload
- val job = coroutineScope.launch {
+ val job = scope.launch {
delay(1) // TODO Introduce boot time
init()
cont.resume(Unit)
@@ -286,18 +325,4 @@ public class SimHost(
onGuestStop(this)
}
}
-
- override fun onStart(ctx: SimExecutionContext) {
- this.ctx = ctx
- this.availableMemory = ctx.machine.memory.map { it.size }.sum()
- this.hypervisor.onStart(ctx)
- }
-
- override fun onStart(ctx: SimExecutionContext, cpu: Int): SimResourceCommand {
- return hypervisor.onStart(ctx, cpu)
- }
-
- override fun onNext(ctx: SimExecutionContext, cpu: Int, remainingWork: Double): SimResourceCommand {
- return hypervisor.onNext(ctx, cpu, remainingWork)
- }
}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHostProvisioner.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHostProvisioner.kt
deleted file mode 100644
index bb03777b..00000000
--- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHostProvisioner.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2021 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 org.opendc.compute.api.Image
-import org.opendc.compute.service.driver.Host
-import org.opendc.metal.Node
-import org.opendc.metal.service.ProvisioningService
-import org.opendc.simulator.compute.SimHypervisorProvider
-import kotlin.coroutines.CoroutineContext
-
-/**
- * A helper class to provision [SimHost]s on top of bare-metal machines using the [ProvisioningService].
- *
- * @param context The [CoroutineContext] to use.
- * @param metal The [ProvisioningService] to use.
- * @param hypervisor The type of hypervisor to use.
- */
-public class SimHostProvisioner(
- private val context: CoroutineContext,
- private val metal: ProvisioningService,
- private val hypervisor: SimHypervisorProvider
-) : AutoCloseable {
- /**
- * The [CoroutineScope] of the service bounded by the lifecycle of the service.
- */
- private val scope = CoroutineScope(context)
-
- /**
- * Provision all machines with a host.
- */
- public suspend fun provisionAll(): List<Host> = coroutineScope {
- metal.nodes().map { node -> async { provision(node) } }.awaitAll()
- }
-
- /**
- * Provision the specified [Node].
- */
- public suspend fun provision(node: Node): Host = coroutineScope {
- val host = SimHost(node, scope, hypervisor)
- metal.deploy(node, Image(node.uid, node.name, mapOf("workload" to host)))
- host
- }
-
- override fun close() {
- scope.cancel()
- }
-}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt
index 0141bc8c..604b69c0 100644
--- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt
@@ -2,7 +2,7 @@ package org.opendc.compute.simulator.power.api
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
-import org.opendc.metal.driver.BareMetalDriver
+import org.opendc.compute.simulator.SimHost
public interface CpuPowerModel {
/**
@@ -18,14 +18,14 @@ public interface CpuPowerModel {
/**
* Emits the values of power consumption for servers.
*
- * @param driver A [BareMetalDriver] that offers host CPU utilization.
+ * @param host A [SimHost] that offers host CPU utilization.
* @param withoutIdle A [Boolean] flag indicates whether (false) add a constant
* power consumption value when the server is idle or (true) not
* with a default value being false.
* @return A [Flow] of values representing the server power draw.
*/
- public fun getPowerDraw(driver: BareMetalDriver, withoutIdle: Boolean = false): Flow<Double> =
- driver.usage.map {
+ public fun getPowerDraw(host: SimHost, withoutIdle: Boolean = false): Flow<Double> =
+ host.machine.usage.map {
computeCpuPower(it)
}
}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimBareMetalDriverTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimBareMetalDriverTest.kt
deleted file mode 100644
index 0d90376e..00000000
--- a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimBareMetalDriverTest.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.flow.collect
-import kotlinx.coroutines.launch
-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.junit.jupiter.api.assertAll
-import org.opendc.compute.api.Image
-import org.opendc.metal.NodeEvent
-import org.opendc.metal.NodeState
-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) }
- )
- }
-
- @Test
- fun testFlopsWorkload() {
- val testScope = TestCoroutineScope()
- val clock = DelayControllerClockAdapter(testScope)
-
- var finalState: NodeState = NodeState.UNKNOWN
- var finalTime = 0L
-
- testScope.launch {
- val driver = SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
- val image = Image(UUID.randomUUID(), "<unnamed>", mapOf("workload" to SimFlopsWorkload(4_000, utilization = 1.0)))
- // Batch driver commands
- withContext(coroutineContext) {
- driver.init()
- driver.setImage(image)
- val node = driver.start()
- node.events.collect { event ->
- when (event) {
- is NodeEvent.StateChanged -> {
- finalState = event.node.state
- finalTime = clock.millis()
- }
- }
- }
- }
- }
-
- testScope.advanceUntilIdle()
- assertAll(
- { assertEquals(NodeState.SHUTOFF, finalState) },
- { assertEquals(501, finalTime) }
- )
- }
-}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt
index 61bff39f..e48fd947 100644
--- a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt
@@ -24,7 +24,6 @@ package org.opendc.compute.simulator
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@@ -39,8 +38,6 @@ import org.opendc.compute.api.Server
import org.opendc.compute.api.ServerState
import org.opendc.compute.api.ServerWatcher
import org.opendc.compute.service.driver.HostEvent
-import org.opendc.metal.Node
-import org.opendc.metal.NodeState
import org.opendc.simulator.compute.SimFairShareHypervisorProvider
import org.opendc.simulator.compute.SimMachineModel
import org.opendc.simulator.compute.model.MemoryUnit
@@ -82,14 +79,8 @@ internal class SimHostTest {
var grantedWork = 0L
var overcommittedWork = 0L
- val node = Node(
- UUID.randomUUID(), "name", emptyMap(), NodeState.SHUTOFF,
- Flavor(machineModel.cpus.size, machineModel.memory.map { it.size }.sum()), Image.EMPTY, emptyFlow()
- )
-
scope.launch {
- val virtDriver = SimHost(node, this, SimFairShareHypervisorProvider())
- val vmm = Image(UUID.randomUUID(), "vmm", mapOf("workload" to virtDriver))
+ val virtDriver = SimHost(UUID.randomUUID(), "test", machineModel, emptyMap(), coroutineContext, clock, SimFairShareHypervisorProvider())
val duration = 5 * 60L
val vmImageA = Image(
UUID.randomUUID(),
@@ -120,13 +111,6 @@ internal class SimHostTest {
)
)
- val metalDriver =
- SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
-
- metalDriver.init()
- metalDriver.setImage(vmm)
- metalDriver.start()
-
delay(5)
val flavor = Flavor(2, 0)
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimProvisioningServiceTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimProvisioningServiceTest.kt
deleted file mode 100644
index 33b3db94..00000000
--- a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimProvisioningServiceTest.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.collect
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestCoroutineScope
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import org.opendc.compute.api.Image
-import org.opendc.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].
- */
-@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 testSmoke() {
- val testScope = TestCoroutineScope()
- val clock = DelayControllerClockAdapter(testScope)
-
- testScope.launch {
- val image = Image(UUID.randomUUID(), "<unnamed>", mapOf("machine" to SimFlopsWorkload(1000)))
- val driver = SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
-
- val provisioner = SimpleProvisioningService()
- provisioner.create(driver)
- delay(5)
- val nodes = provisioner.nodes()
- val node = provisioner.deploy(nodes.first(), image)
- node.events.collect { println(it) }
- }
-
- testScope.advanceUntilIdle()
- }
-}
diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt
index d4d88fb1..9d034a5d 100644
--- a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt
+++ b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt
@@ -1,18 +1,21 @@
package org.opendc.compute.simulator.power
import io.mockk.*
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runBlockingTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
+import org.opendc.compute.simulator.SimHost
import org.opendc.compute.simulator.power.api.CpuPowerModel
import org.opendc.compute.simulator.power.models.*
-import org.opendc.metal.driver.BareMetalDriver
+import org.opendc.simulator.compute.SimBareMetalMachine
import java.util.stream.Stream
import kotlin.math.pow
+@OptIn(ExperimentalCoroutinesApi::class)
internal class CpuPowerModelTest {
private val epsilon = 10.0.pow(-3)
private val cpuUtil = .9
@@ -44,21 +47,24 @@ internal class CpuPowerModelTest {
powerModel: CpuPowerModel,
expectedPowerConsumption: Double
) {
- val cpuLoads = flowOf(cpuUtil, cpuUtil, cpuUtil)
- val bareMetalDriver = mockkClass(BareMetalDriver::class)
- every { bareMetalDriver.usage } returns cpuLoads
+ runBlockingTest {
+ val cpuLoads = flowOf(cpuUtil, cpuUtil, cpuUtil).stateIn(this)
+ val bareMetalDriver = mockkClass(SimHost::class)
+ val machine = mockkClass(SimBareMetalMachine::class)
+ every { bareMetalDriver.machine } returns machine
+ every { machine.usage } returns cpuLoads
- runBlocking {
val serverPowerDraw = powerModel.getPowerDraw(bareMetalDriver)
- assertEquals(serverPowerDraw.count(), cpuLoads.count())
assertEquals(
serverPowerDraw.first().toDouble(),
flowOf(expectedPowerConsumption).first().toDouble(),
epsilon
)
+
+ verify(exactly = 1) { bareMetalDriver.machine }
+ verify(exactly = 1) { machine.usage }
}
- verify(exactly = 1) { bareMetalDriver.usage }
}
@Suppress("unused")
diff --git a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt
index a5cf4fc0..f2f53917 100644
--- a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt
+++ b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.experiments.capelin.experiment
+package org.opendc.experiments.capelin
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -39,23 +39,20 @@ import org.opendc.compute.api.ServerState
import org.opendc.compute.api.ServerWatcher
import org.opendc.compute.service.ComputeService
import org.opendc.compute.service.ComputeServiceEvent
+import org.opendc.compute.service.driver.Host
import org.opendc.compute.service.driver.HostEvent
+import org.opendc.compute.service.driver.HostListener
+import org.opendc.compute.service.driver.HostState
import org.opendc.compute.service.internal.ComputeServiceImpl
import org.opendc.compute.service.scheduler.AllocationPolicy
-import org.opendc.compute.simulator.SimBareMetalDriver
import org.opendc.compute.simulator.SimHost
-import org.opendc.compute.simulator.SimHostProvisioner
import org.opendc.experiments.capelin.monitor.ExperimentMonitor
import org.opendc.experiments.capelin.trace.Sc20StreamingParquetTraceReader
import org.opendc.format.environment.EnvironmentReader
import org.opendc.format.trace.TraceReader
-import org.opendc.metal.NODE_CLUSTER
-import org.opendc.metal.NodeEvent
-import org.opendc.metal.service.ProvisioningService
import org.opendc.simulator.compute.SimFairShareHypervisorProvider
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 org.opendc.trace.core.EventTracer
import java.io.File
@@ -72,20 +69,20 @@ private val logger = KotlinLogging.logger {}
/**
* Construct the failure domain for the experiments.
*/
-public suspend fun createFailureDomain(
+public fun createFailureDomain(
coroutineScope: CoroutineScope,
clock: Clock,
seed: Int,
failureInterval: Double,
- bareMetalProvisioner: ProvisioningService,
+ service: ComputeService,
chan: Channel<Unit>
): CoroutineScope {
val job = coroutineScope.launch {
chan.receive()
val random = Random(seed)
val injectors = mutableMapOf<String, FaultInjector>()
- for (node in bareMetalProvisioner.nodes()) {
- val cluster = node.metadata[NODE_CLUSTER] as String
+ for (host in service.hosts) {
+ val cluster = host.meta["cluster"] as String
val injector =
injectors.getOrPut(cluster) {
createFaultInjector(
@@ -95,7 +92,7 @@ public suspend fun createFailureDomain(
failureInterval
)
}
- injector.enqueue(node.metadata["driver"] as FailureDomain)
+ injector.enqueue(host as SimHost)
}
}
return CoroutineScope(coroutineScope.coroutineContext + job)
@@ -139,41 +136,39 @@ public fun createTraceReader(
)
}
-public data class ProvisionerResult(
- val metal: ProvisioningService,
- val provisioner: SimHostProvisioner,
- val compute: ComputeServiceImpl
-)
-
/**
- * Construct the environment for a VM provisioner and return the provisioner instance.
+ * Construct the environment for a simulated compute service..
*/
-public suspend fun createProvisioner(
+public fun createComputeService(
coroutineScope: CoroutineScope,
clock: Clock,
environmentReader: EnvironmentReader,
allocationPolicy: AllocationPolicy,
eventTracer: EventTracer
-): ProvisionerResult {
- 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 provisioner = SimHostProvisioner(coroutineScope.coroutineContext, bareMetalProvisioner, SimFairShareHypervisorProvider())
- val hosts = provisioner.provisionAll()
+): ComputeServiceImpl {
+ val hosts = environmentReader
+ .use { it.read() }
+ .map { def ->
+ SimHost(
+ def.uid,
+ def.name,
+ def.model,
+ def.meta,
+ coroutineScope.coroutineContext,
+ clock,
+ SimFairShareHypervisorProvider(),
+ def.powerModel
+ )
+ }
- val scheduler = ComputeService(coroutineScope.coroutineContext, clock, eventTracer, allocationPolicy) as ComputeServiceImpl
+ val scheduler =
+ ComputeService(coroutineScope.coroutineContext, clock, eventTracer, allocationPolicy) as ComputeServiceImpl
for (host in hosts) {
scheduler.addHost(host)
}
- // Wait for the hypervisors to be spawned
- delay(10)
-
- return ProvisionerResult(bareMetalProvisioner, provisioner, scheduler)
+ return scheduler
}
/**
@@ -186,25 +181,16 @@ public fun attachMonitor(
scheduler: ComputeService,
monitor: ExperimentMonitor
) {
-
- val hypervisors = scheduler.hosts
-
- // Monitor hypervisor events
- for (hypervisor in hypervisors) {
- // TODO Do not expose Host directly but use Hypervisor class.
- val server = (hypervisor as SimHost).node
- monitor.reportHostStateChange(clock.millis(), hypervisor, server)
- server.events
- .onEach { event ->
- val time = clock.millis()
- when (event) {
- is NodeEvent.StateChanged -> {
- monitor.reportHostStateChange(time, hypervisor, event.node)
- }
- }
+ // Monitor host events
+ for (host in scheduler.hosts) {
+ monitor.reportHostStateChange(clock.millis(), host, HostState.UP)
+ host.addListener(object : HostListener {
+ override fun onStateChanged(host: Host, newState: HostState) {
+ monitor.reportHostStateChange(clock.millis(), host, newState)
}
- .launchIn(coroutineScope)
- hypervisor.events
+ })
+
+ host.events
.onEach { event ->
when (event) {
is HostEvent.SliceFinished -> monitor.reportHostSlice(
@@ -216,15 +202,14 @@ public fun attachMonitor(
event.cpuUsage,
event.cpuDemand,
event.numberOfDeployedImages,
- (event.driver as SimHost).node
+ event.driver
)
}
}
.launchIn(coroutineScope)
- val driver = server.metadata["driver"] as SimBareMetalDriver
- driver.powerDraw
- .onEach { monitor.reportPowerConsumption(server, it) }
+ (host as SimHost).powerDraw
+ .onEach { monitor.reportPowerConsumption(host, it) }
.launchIn(coroutineScope)
}
diff --git a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt
index ff0a026d..f9c96bb6 100644
--- a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt
+++ b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt
@@ -35,10 +35,6 @@ import org.opendc.compute.service.scheduler.NumberOfActiveServersAllocationPolic
import org.opendc.compute.service.scheduler.ProvisionedCoresAllocationPolicy
import org.opendc.compute.service.scheduler.RandomAllocationPolicy
import org.opendc.compute.simulator.allocation.*
-import org.opendc.experiments.capelin.experiment.attachMonitor
-import org.opendc.experiments.capelin.experiment.createFailureDomain
-import org.opendc.experiments.capelin.experiment.createProvisioner
-import org.opendc.experiments.capelin.experiment.processTrace
import org.opendc.experiments.capelin.model.CompositeWorkload
import org.opendc.experiments.capelin.model.OperationalPhenomena
import org.opendc.experiments.capelin.model.Topology
@@ -157,7 +153,7 @@ public abstract class Portfolio(name: String) : Experiment(name) {
)
testScope.launch {
- val (bareMetalProvisioner, provisioner, scheduler) = createProvisioner(
+ val scheduler = createComputeService(
this,
clock,
environment,
@@ -172,7 +168,7 @@ public abstract class Portfolio(name: String) : Experiment(name) {
clock,
seeder.nextInt(),
operationalPhenomena.failureFrequency,
- bareMetalProvisioner,
+ scheduler,
chan
)
} else {
@@ -197,7 +193,6 @@ public abstract class Portfolio(name: String) : Experiment(name) {
failureDomain?.cancel()
scheduler.close()
- provisioner.close()
}
try {
diff --git a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMonitor.kt b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMonitor.kt
index 1e42cf56..14cc06dc 100644
--- a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMonitor.kt
+++ b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMonitor.kt
@@ -26,7 +26,7 @@ import org.opendc.compute.api.Server
import org.opendc.compute.api.ServerState
import org.opendc.compute.service.ComputeServiceEvent
import org.opendc.compute.service.driver.Host
-import org.opendc.metal.Node
+import org.opendc.compute.service.driver.HostState
import java.io.Closeable
/**
@@ -41,17 +41,12 @@ public interface ExperimentMonitor : Closeable {
/**
* This method is invoked when the state of a host changes.
*/
- public fun reportHostStateChange(
- time: Long,
- driver: Host,
- host: Node
- ) {
- }
+ public fun reportHostStateChange(time: Long, host: Host, newState: HostState) {}
/**
* Report the power consumption of a host.
*/
- public fun reportPowerConsumption(host: Node, draw: Double) {}
+ public fun reportPowerConsumption(host: Host, draw: Double) {}
/**
* This method is invoked for a host for each slice that is finishes.
@@ -65,7 +60,7 @@ public interface ExperimentMonitor : Closeable {
cpuUsage: Double,
cpuDemand: Double,
numberOfDeployedImages: Int,
- host: Node,
+ host: Host,
duration: Long = 5 * 60 * 1000L
) {
}
diff --git a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ParquetExperimentMonitor.kt b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ParquetExperimentMonitor.kt
index 98052214..c9d57a98 100644
--- a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ParquetExperimentMonitor.kt
+++ b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ParquetExperimentMonitor.kt
@@ -27,11 +27,11 @@ import org.opendc.compute.api.Server
import org.opendc.compute.api.ServerState
import org.opendc.compute.service.ComputeServiceEvent
import org.opendc.compute.service.driver.Host
+import org.opendc.compute.service.driver.HostState
import org.opendc.experiments.capelin.telemetry.HostEvent
import org.opendc.experiments.capelin.telemetry.ProvisionerEvent
import org.opendc.experiments.capelin.telemetry.parquet.ParquetHostEventWriter
import org.opendc.experiments.capelin.telemetry.parquet.ParquetProvisionerEventWriter
-import org.opendc.metal.Node
import java.io.File
/**
@@ -51,7 +51,7 @@ public class ParquetExperimentMonitor(base: File, partition: String, bufferSize:
File(base, "provisioner-metrics/$partition/data.parquet"),
bufferSize
)
- private val currentHostEvent = mutableMapOf<Node, HostEvent>()
+ private val currentHostEvent = mutableMapOf<Host, HostEvent>()
private var startTime = -1L
override fun reportVmStateChange(time: Long, server: Server, newState: ServerState) {
@@ -63,12 +63,8 @@ public class ParquetExperimentMonitor(base: File, partition: String, bufferSize:
}
}
- override fun reportHostStateChange(
- time: Long,
- driver: Host,
- host: Node
- ) {
- logger.debug { "Host ${host.uid} changed state ${host.state} [$time]" }
+ override fun reportHostStateChange(time: Long, host: Host, newState: HostState) {
+ logger.debug { "Host ${host.uid} changed state $newState [$time]" }
val previousEvent = currentHostEvent[host]
@@ -97,9 +93,9 @@ public class ParquetExperimentMonitor(base: File, partition: String, bufferSize:
)
}
- private val lastPowerConsumption = mutableMapOf<Node, Double>()
+ private val lastPowerConsumption = mutableMapOf<Host, Double>()
- override fun reportPowerConsumption(host: Node, draw: Double) {
+ override fun reportPowerConsumption(host: Host, draw: Double) {
lastPowerConsumption[host] = draw
}
@@ -112,7 +108,7 @@ public class ParquetExperimentMonitor(base: File, partition: String, bufferSize:
cpuUsage: Double,
cpuDemand: Double,
numberOfDeployedImages: Int,
- host: Node,
+ host: Host,
duration: Long
) {
val previousEvent = currentHostEvent[host]
@@ -130,7 +126,7 @@ public class ParquetExperimentMonitor(base: File, partition: String, bufferSize:
cpuUsage,
cpuDemand,
lastPowerConsumption[host] ?: 200.0,
- host.flavor.cpuCount
+ host.model.cpuCount
)
currentHostEvent[host] = event
@@ -148,7 +144,7 @@ public class ParquetExperimentMonitor(base: File, partition: String, bufferSize:
cpuUsage,
cpuDemand,
lastPowerConsumption[host] ?: 200.0,
- host.flavor.cpuCount
+ host.model.cpuCount
)
currentHostEvent[host] = event
@@ -168,7 +164,7 @@ public class ParquetExperimentMonitor(base: File, partition: String, bufferSize:
cpuUsage,
cpuDemand,
lastPowerConsumption[host] ?: 200.0,
- host.flavor.cpuCount
+ host.model.cpuCount
)
currentHostEvent[host] = event
diff --git a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/HostEvent.kt b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/HostEvent.kt
index e7b6a7bb..899fc9b1 100644
--- a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/HostEvent.kt
+++ b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/HostEvent.kt
@@ -22,7 +22,7 @@
package org.opendc.experiments.capelin.telemetry
-import org.opendc.metal.Node
+import org.opendc.compute.service.driver.Host
/**
* A periodic report of the host machine metrics.
@@ -30,7 +30,7 @@ import org.opendc.metal.Node
public data class HostEvent(
override val timestamp: Long,
public val duration: Long,
- public val node: Node,
+ public val host: Host,
public val vmCount: Int,
public val requestedBurst: Long,
public val grantedBurst: Long,
diff --git a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/parquet/ParquetHostEventWriter.kt b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/parquet/ParquetHostEventWriter.kt
index b4fdd66a..4a3e7963 100644
--- a/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/parquet/ParquetHostEventWriter.kt
+++ b/simulator/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/telemetry/parquet/ParquetHostEventWriter.kt
@@ -41,8 +41,8 @@ public class ParquetHostEventWriter(path: File, bufferSize: Int) :
// record.put("portfolio_id", event.run.parent.parent.id)
// record.put("scenario_id", event.run.parent.id)
// record.put("run_id", event.run.id)
- record.put("host_id", event.node.name)
- record.put("state", event.node.state.name)
+ record.put("host_id", event.host.name)
+ record.put("state", event.host.state.name)
record.put("timestamp", event.timestamp)
record.put("duration", event.duration)
record.put("vm_count", event.vmCount)
diff --git a/simulator/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt b/simulator/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
index dfc6b90b..9921c209 100644
--- a/simulator/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
+++ b/simulator/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
@@ -33,12 +33,9 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
import org.opendc.compute.api.ComputeWorkload
+import org.opendc.compute.service.driver.Host
import org.opendc.compute.service.internal.ComputeServiceImpl
import org.opendc.compute.service.scheduler.AvailableCoreMemoryAllocationPolicy
-import org.opendc.experiments.capelin.experiment.attachMonitor
-import org.opendc.experiments.capelin.experiment.createFailureDomain
-import org.opendc.experiments.capelin.experiment.createProvisioner
-import org.opendc.experiments.capelin.experiment.processTrace
import org.opendc.experiments.capelin.model.Workload
import org.opendc.experiments.capelin.monitor.ExperimentMonitor
import org.opendc.experiments.capelin.trace.Sc20ParquetTraceReader
@@ -46,7 +43,6 @@ import org.opendc.experiments.capelin.trace.Sc20RawParquetTraceReader
import org.opendc.format.environment.EnvironmentReader
import org.opendc.format.environment.sc20.Sc20ClusterEnvironmentReader
import org.opendc.format.trace.TraceReader
-import org.opendc.metal.Node
import org.opendc.simulator.utils.DelayControllerClockAdapter
import org.opendc.trace.core.EventTracer
import java.io.File
@@ -101,15 +97,13 @@ class CapelinIntegrationTest {
val tracer = EventTracer(clock)
testScope.launch {
- val res = createProvisioner(
+ scheduler = createComputeService(
this,
clock,
environmentReader,
allocationPolicy,
tracer
)
- val bareMetalProvisioner = res.metal
- scheduler = res.compute
val failureDomain = if (failures) {
println("ENABLING failures")
@@ -118,7 +112,7 @@ class CapelinIntegrationTest {
clock,
seed,
24.0 * 7,
- bareMetalProvisioner,
+ scheduler,
chan
)
} else {
@@ -140,7 +134,6 @@ class CapelinIntegrationTest {
failureDomain?.cancel()
scheduler.close()
monitor.close()
- res.provisioner.close()
}
runSimulation()
@@ -166,7 +159,7 @@ class CapelinIntegrationTest {
val tracer = EventTracer(clock)
testScope.launch {
- val (_, provisioner, scheduler) = createProvisioner(
+ val scheduler = createComputeService(
this,
clock,
environmentReader,
@@ -187,7 +180,6 @@ class CapelinIntegrationTest {
scheduler.close()
monitor.close()
- provisioner.close()
}
runSimulation()
@@ -241,7 +233,7 @@ class CapelinIntegrationTest {
cpuUsage: Double,
cpuDemand: Double,
numberOfDeployedImages: Int,
- host: Node,
+ host: Host,
duration: Long
) {
totalRequestedBurst += requestedBurst
diff --git a/simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/UnderspecificationExperiment.kt b/simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/UnderspecificationExperiment.kt
index 7b9d70ed..57d1a4a0 100644
--- a/simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/UnderspecificationExperiment.kt
+++ b/simulator/opendc-experiments/opendc-experiments-sc18/src/main/kotlin/org/opendc/experiments/sc18/UnderspecificationExperiment.kt
@@ -26,12 +26,11 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.test.TestCoroutineScope
import org.opendc.compute.service.ComputeService
import org.opendc.compute.service.scheduler.NumberOfActiveServersAllocationPolicy
-import org.opendc.compute.simulator.SimHostProvisioner
+import org.opendc.compute.simulator.SimHost
import org.opendc.format.environment.sc18.Sc18EnvironmentReader
import org.opendc.format.trace.gwf.GwfTraceReader
import org.opendc.harness.dsl.Experiment
import org.opendc.harness.dsl.anyOf
-import org.opendc.metal.service.ProvisioningService
import org.opendc.simulator.compute.SimSpaceSharedHypervisorProvider
import org.opendc.simulator.utils.DelayControllerClockAdapter
import org.opendc.trace.core.EventTracer
@@ -84,16 +83,20 @@ public class UnderspecificationExperiment : Experiment("underspecification") {
}
testScope.launch {
- val environment = Sc18EnvironmentReader(FileInputStream(File(environment)))
- .use { it.construct(testScope, clock) }
+ val hosts = Sc18EnvironmentReader(FileInputStream(File(environment)))
+ .use { it.read() }
+ .map { def ->
+ SimHost(
+ def.uid,
+ def.name,
+ def.model,
+ def.meta,
+ testScope.coroutineContext,
+ clock,
+ SimSpaceSharedHypervisorProvider()
+ )
+ }
- val bareMetal = environment.platforms[0].zones[0].services[ProvisioningService]
-
- // Wait for the bare metal nodes to be spawned
- delay(10)
-
- val provisioner = SimHostProvisioner(testScope.coroutineContext, bareMetal, SimSpaceSharedHypervisorProvider())
- val hosts = provisioner.provisionAll()
val compute = ComputeService(
testScope.coroutineContext,
clock,
@@ -103,9 +106,6 @@ public class UnderspecificationExperiment : Experiment("underspecification") {
hosts.forEach { compute.addHost(it) }
- // Wait for the hypervisors to be spawned
- delay(10)
-
val scheduler = StageWorkflowService(
testScope,
clock,
diff --git a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt
index 1f73bb61..81fe04a1 100644
--- a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/EnvironmentReader.kt
@@ -22,17 +22,15 @@
package org.opendc.format.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].
*/
public interface EnvironmentReader : Closeable {
/**
- * Construct an [Environment] in the specified [CoroutineScope].
+ * Read the environment into a list.
*/
- public suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment
+ public fun read(): List<MachineDef>
}
diff --git a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/Metadata.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/MachineDef.kt
index ca98dab0..b5b3b84b 100644
--- a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/Metadata.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/MachineDef.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2021 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,16 @@
* SOFTWARE.
*/
-package org.opendc.metal
+package org.opendc.format.environment
-/*
- * Common metadata keys for bare-metal nodes.
- */
+import org.opendc.compute.simulator.power.api.CpuPowerModel
+import org.opendc.simulator.compute.SimMachineModel
+import java.util.*
-/**
- * The cluster to which the node belongs.
- */
-public const val NODE_CLUSTER: String = "bare-metal:cluster"
+public data class MachineDef(
+ val uid: UUID,
+ val name: String,
+ val meta: Map<String, Any>,
+ val model: SimMachineModel,
+ val powerModel: CpuPowerModel
+)
diff --git a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt
index bbbbe87c..3da8d0b3 100644
--- a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc18/Sc18EnvironmentReader.kt
@@ -25,21 +25,14 @@ package org.opendc.format.environment.sc18
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.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.compute.simulator.power.models.ConstantPowerModel
import org.opendc.format.environment.EnvironmentReader
-import org.opendc.metal.service.ProvisioningService
-import org.opendc.metal.service.SimpleProvisioningService
+import org.opendc.format.environment.MachineDef
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.time.Clock
import java.util.*
/**
@@ -55,9 +48,12 @@ public class Sc18EnvironmentReader(input: InputStream, mapper: ObjectMapper = ja
*/
private val setup: Setup = mapper.readValue(input)
- override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
+ /**
+ * Read the environment.
+ */
+ public override fun read(): List<MachineDef> {
var counter = 0
- val nodes = setup.rooms.flatMap { room ->
+ return setup.rooms.flatMap { room ->
room.objects.flatMap { roomObject ->
when (roomObject) {
is RoomObject.Rack -> {
@@ -75,35 +71,18 @@ public class Sc18EnvironmentReader(input: InputStream, mapper: ObjectMapper = ja
else -> throw IllegalArgumentException("The cpu id $id is not recognized")
}
}
- SimBareMetalDriver(
- coroutineScope,
- clock,
- UUID.randomUUID(),
- "node-${counter++}",
+ MachineDef(
+ UUID(0L, counter++.toLong()),
+ "node-$counter",
emptyMap(),
- SimMachineModel(cores, listOf(MemoryUnit("", "", 2300.0, 16000)))
+ SimMachineModel(cores, listOf(MemoryUnit("", "", 2300.0, 16000))),
+ ConstantPowerModel(0.0)
)
}
}
}
}
}
-
- val provisioningService = SimpleProvisioningService()
- for (node in nodes) {
- provisioningService.create(node)
- }
-
- val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
- val platform = Platform(
- UUID.randomUUID(),
- "sc18-platform",
- listOf(
- Zone(UUID.randomUUID(), "zone", serviceRegistry)
- )
- )
-
- return Environment(setup.name, null, listOf(platform))
}
override fun close() {}
diff --git a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt
index 998f9cd6..9a06a40f 100644
--- a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt
@@ -22,17 +22,9 @@
package org.opendc.format.environment.sc20
-import kotlinx.coroutines.CoroutineScope
-import org.opendc.compute.simulator.SimBareMetalDriver
import org.opendc.compute.simulator.power.models.LinearPowerModel
-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.metal.NODE_CLUSTER
-import org.opendc.metal.service.ProvisioningService
-import org.opendc.metal.service.SimpleProvisioningService
+import org.opendc.format.environment.MachineDef
import org.opendc.simulator.compute.SimMachineModel
import org.opendc.simulator.compute.model.MemoryUnit
import org.opendc.simulator.compute.model.ProcessingNode
@@ -40,7 +32,6 @@ import org.opendc.simulator.compute.model.ProcessingUnit
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
-import java.time.Clock
import java.util.*
/**
@@ -54,8 +45,7 @@ public class Sc20ClusterEnvironmentReader(
public constructor(file: File) : this(FileInputStream(file))
- @Suppress("BlockingMethodInNonBlockingContext")
- override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
+ public override fun read(): List<MachineDef> {
var clusterIdCol = 0
var speedCol = 0
var numberOfHostsCol = 0
@@ -69,7 +59,7 @@ public class Sc20ClusterEnvironmentReader(
var memoryPerHost: Long
var coresPerHost: Int
- val nodes = mutableListOf<SimBareMetalDriver>()
+ val nodes = mutableListOf<MachineDef>()
val random = Random(0)
input.bufferedReader().use { reader ->
@@ -103,12 +93,10 @@ public class Sc20ClusterEnvironmentReader(
repeat(numberOfHosts) {
nodes.add(
- SimBareMetalDriver(
- coroutineScope,
- clock,
+ MachineDef(
UUID(random.nextLong(), random.nextLong()),
"node-$clusterId-$it",
- mapOf(NODE_CLUSTER to clusterId),
+ mapOf("cluster" to clusterId),
SimMachineModel(
List(coresPerHost) { coreId ->
ProcessingUnit(unknownProcessingNode, coreId, speed)
@@ -125,22 +113,7 @@ public class Sc20ClusterEnvironmentReader(
}
}
- val provisioningService = SimpleProvisioningService()
- for (node in nodes) {
- provisioningService.create(node)
- }
-
- val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
-
- val platform = Platform(
- UUID.randomUUID(),
- "sc20-platform",
- listOf(
- Zone(UUID.randomUUID(), "zone", serviceRegistry)
- )
- )
-
- return Environment("SC20 Environment", null, listOf(platform))
+ return nodes
}
override fun close() {}
diff --git a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt
index 6cf65f7f..effd0286 100644
--- a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt
+++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt
@@ -25,22 +25,14 @@ package org.opendc.format.environment.sc20
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.simulator.SimBareMetalDriver
import org.opendc.compute.simulator.power.models.LinearPowerModel
-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.metal.service.ProvisioningService
-import org.opendc.metal.service.SimpleProvisioningService
+import org.opendc.format.environment.MachineDef
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.time.Clock
import java.util.*
/**
@@ -55,9 +47,12 @@ public class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = ja
*/
private val setup: Setup = mapper.readValue(input)
- override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
+ /**
+ * Read the environment.
+ */
+ public override fun read(): List<MachineDef> {
var counter = 0
- val nodes = setup.rooms.flatMap { room ->
+ return setup.rooms.flatMap { room ->
room.objects.flatMap { roomObject ->
when (roomObject) {
is RoomObject.Rack -> {
@@ -81,11 +76,9 @@ public class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = ja
else -> throw IllegalArgumentException("The cpu id $id is not recognized")
}
}
- SimBareMetalDriver(
- coroutineScope,
- clock,
- UUID.randomUUID(),
- "node-${counter++}",
+ MachineDef(
+ UUID(0L, counter++.toLong()),
+ "node-$counter",
emptyMap(),
SimMachineModel(cores, memories),
// For now we assume a simple linear load model with an idle draw of ~200W and a maximum
@@ -98,23 +91,6 @@ public class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = ja
}
}
}
-
- val provisioningService = SimpleProvisioningService()
- for (node in nodes) {
- provisioningService.create(node)
- }
-
- val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
-
- val platform = Platform(
- UUID.randomUUID(),
- "sc20-platform",
- listOf(
- Zone(UUID.randomUUID(), "zone", serviceRegistry)
- )
- )
-
- return Environment(setup.name, null, listOf(platform))
}
override fun close() {}
diff --git a/simulator/opendc-metal/build.gradle.kts b/simulator/opendc-metal/build.gradle.kts
deleted file mode 100644
index 9207de18..00000000
--- a/simulator/opendc-metal/build.gradle.kts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 = "Bare-metal provisioning in OpenDC"
-
-/* Build configuration */
-plugins {
- `kotlin-library-conventions`
-}
-
-dependencies {
- api(platform(project(":opendc-platform")))
- api(project(":opendc-core"))
- api(project(":opendc-compute:opendc-compute-api"))
- api(project(":opendc-trace:opendc-trace-core"))
- implementation(project(":opendc-utils"))
-
- implementation("io.github.microutils:kotlin-logging")
-}
diff --git a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/Node.kt b/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/Node.kt
deleted file mode 100644
index 1c5c7a8d..00000000
--- a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/Node.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2021 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.metal
-
-import kotlinx.coroutines.flow.Flow
-import org.opendc.compute.api.Flavor
-import org.opendc.compute.api.Image
-import org.opendc.core.Identity
-import java.util.UUID
-
-/**
- * A bare-metal compute node.
- */
-public data class Node(
- /**
- * The unique identifier of the node.
- */
- public override val uid: UUID,
-
- /**
- * The optional name of the node.
- */
- public override val name: String,
-
- /**
- * Metadata of the node.
- */
- public val metadata: Map<String, Any>,
-
- /**
- * The last known state of the compute node.
- */
- public val state: NodeState,
-
- /**
- * The flavor of the node.
- */
- public val flavor: Flavor,
-
- /**
- * The boot image of the node.
- */
- public val image: Image,
-
- /**
- * The events that are emitted by the node.
- */
- public val events: Flow<NodeEvent>
-) : Identity {
- override fun hashCode(): Int = uid.hashCode()
- override fun equals(other: Any?): Boolean = other is Node && uid == other.uid
-}
diff --git a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeEvent.kt b/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeEvent.kt
deleted file mode 100644
index 30ce423c..00000000
--- a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeEvent.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2021 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.metal
-
-/**
- * An event that is emitted by a [Node].
- */
-public sealed class NodeEvent {
- /**
- * The node that emitted the event.
- */
- public abstract val node: Node
-
- /**
- * This event is emitted when the state of [node] changes.
- *
- * @property node The node of which the state changed.
- * @property previousState The previous state of the node.
- */
- public data class StateChanged(override val node: Node, val previousState: NodeState) : NodeEvent()
-}
diff --git a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeState.kt b/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeState.kt
deleted file mode 100644
index f1d4ea2e..00000000
--- a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/NodeState.kt
+++ /dev/null
@@ -1,55 +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 org.opendc.metal
-
-/**
- * An enumeration describing the possible states of a bare-metal compute node.
- */
-public enum class NodeState {
- /**
- * The node is booting.
- */
- BOOT,
-
- /**
- * The node is powered off.
- */
- SHUTOFF,
-
- /**
- * The node is active and running.
- */
- ACTIVE,
-
- /**
- * The node is in error.
- */
- ERROR,
-
- /**
- * The state of the node is unknown.
- */
- UNKNOWN,
-}
diff --git a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/driver/BareMetalDriver.kt b/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/driver/BareMetalDriver.kt
deleted file mode 100644
index 3b15be94..00000000
--- a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/driver/BareMetalDriver.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2021 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.metal.driver
-
-import kotlinx.coroutines.flow.Flow
-import org.opendc.compute.api.Image
-import org.opendc.compute.api.Server
-import org.opendc.core.services.AbstractServiceKey
-import org.opendc.metal.Node
-import java.util.UUID
-
-/**
- * A driver interface for the management interface of a bare-metal compute node.
- */
-public interface BareMetalDriver {
- /**
- * The [Node] that is controlled by this driver.
- */
- public val node: Flow<Node>
-
- /**
- * The amount of work done by the machine in percentage with respect to the total amount of processing power
- * available.
- */
- public val usage: Flow<Double>
-
- /**
- * Initialize the driver.
- */
- public suspend fun init(): Node
-
- /**
- * Start the bare metal node with the specified boot disk image.
- */
- public suspend fun start(): Node
-
- /**
- * Stop the bare metal node if it is running.
- */
- public suspend fun stop(): Node
-
- /**
- * Reboot the bare metal node.
- */
- public suspend fun reboot(): Node
-
- /**
- * Update the boot disk image of the compute node.
- *
- * Changing the boot disk image of node does not affect it while the node is running. In order to start the new boot
- * disk image, the compute node must be restarted.
- */
- public suspend fun setImage(image: Image): Node
-
- /**
- * Obtain the state of the compute node.
- */
- public suspend fun refresh(): Node
-
- /**
- * A key that allows access to the [BareMetalDriver] instance from a [Server] that runs on the bare-metal machine.
- */
- public companion object Key : AbstractServiceKey<BareMetalDriver>(UUID.randomUUID(), "bare-metal:driver")
-}
diff --git a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/ProvisioningService.kt b/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/ProvisioningService.kt
deleted file mode 100644
index 6548767e..00000000
--- a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/ProvisioningService.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2021 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.metal.service
-
-import org.opendc.compute.api.Image
-import org.opendc.core.services.AbstractServiceKey
-import org.opendc.metal.Node
-import org.opendc.metal.driver.BareMetalDriver
-import java.util.UUID
-
-/**
- * A cloud platform service for provisioning bare-metal compute nodes on the platform.
- */
-public interface ProvisioningService {
- /**
- * Create a new bare-metal compute node.
- */
- public suspend fun create(driver: BareMetalDriver): Node
-
- /**
- * Obtain the available nodes.
- */
- public suspend fun nodes(): Set<Node>
-
- /**
- * Refresh the state of a compute node.
- */
- public suspend fun refresh(node: Node): Node
-
- /**
- * Deploy the specified [Image] on a compute node.
- */
- public suspend fun deploy(node: Node, image: Image): Node
-
- /**
- * Stop the specified [Node] .
- */
- public suspend fun stop(node: Node): Node
-
- /**
- * The service key of this service.
- */
- public companion object Key : AbstractServiceKey<ProvisioningService>(UUID.randomUUID(), "provisioner")
-}
diff --git a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/SimpleProvisioningService.kt b/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/SimpleProvisioningService.kt
deleted file mode 100644
index 2d6353c8..00000000
--- a/simulator/opendc-metal/src/main/kotlin/org/opendc/metal/service/SimpleProvisioningService.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2021 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.metal.service
-
-import kotlinx.coroutines.CancellationException
-import org.opendc.compute.api.Image
-import org.opendc.metal.Node
-import org.opendc.metal.driver.BareMetalDriver
-
-/**
- * A very basic implementation of the [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 {
- val node = driver.init()
- nodes[node] = driver
- return node
- }
-
- override suspend fun nodes(): Set<Node> = nodes.keys
-
- override suspend fun refresh(node: Node): Node {
- return nodes[node]!!.refresh()
- }
-
- override suspend fun deploy(node: Node, image: Image): Node {
- val driver = nodes[node]!!
- driver.setImage(image)
- return driver.reboot()
- }
-
- override suspend fun stop(node: Node): Node {
- val driver = nodes[node]!!
- return try {
- driver.stop()
- } catch (e: CancellationException) {
- node
- }
- }
-}
diff --git a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt
index 482fe754..b9aeecb8 100644
--- a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt
+++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/Main.kt
@@ -46,11 +46,11 @@ import org.opendc.compute.service.scheduler.NumberOfActiveServersAllocationPolic
import org.opendc.compute.service.scheduler.ProvisionedCoresAllocationPolicy
import org.opendc.compute.service.scheduler.RandomAllocationPolicy
import org.opendc.compute.simulator.allocation.*
-import org.opendc.experiments.capelin.experiment.attachMonitor
-import org.opendc.experiments.capelin.experiment.createFailureDomain
-import org.opendc.experiments.capelin.experiment.createProvisioner
-import org.opendc.experiments.capelin.experiment.processTrace
+import org.opendc.experiments.capelin.attachMonitor
+import org.opendc.experiments.capelin.createComputeService
+import org.opendc.experiments.capelin.createFailureDomain
import org.opendc.experiments.capelin.model.Workload
+import org.opendc.experiments.capelin.processTrace
import org.opendc.experiments.capelin.trace.Sc20ParquetTraceReader
import org.opendc.experiments.capelin.trace.Sc20RawParquetTraceReader
import org.opendc.format.trace.sc20.Sc20PerformanceInterferenceReader
@@ -247,7 +247,7 @@ public class RunnerCli : CliktCommand(name = "runner") {
val tracer = EventTracer(clock)
testScope.launch {
- val (bareMetalProvisioner, provisioner, scheduler) = createProvisioner(
+ val scheduler = createComputeService(
this,
clock,
environment,
@@ -262,7 +262,7 @@ public class RunnerCli : CliktCommand(name = "runner") {
clock,
seeder.nextInt(),
operational.get("failureFrequency", Number::class.java)?.toDouble() ?: 24.0 * 7,
- bareMetalProvisioner,
+ scheduler,
chan
)
} else {
@@ -287,7 +287,6 @@ public class RunnerCli : CliktCommand(name = "runner") {
failureDomain?.cancel()
scheduler.close()
- provisioner.close()
}
try {
diff --git a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt
index 2f11347d..e7e99a3d 100644
--- a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt
+++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt
@@ -28,36 +28,24 @@ 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 kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
import org.bson.Document
import org.bson.types.ObjectId
-import org.opendc.compute.simulator.SimBareMetalDriver
import org.opendc.compute.simulator.power.models.LinearPowerModel
-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.metal.NODE_CLUSTER
-import org.opendc.metal.service.ProvisioningService
-import org.opendc.metal.service.SimpleProvisioningService
+import org.opendc.format.environment.MachineDef
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.
*/
public class TopologyParser(private val collection: MongoCollection<Document>, private val id: ObjectId) : EnvironmentReader {
- /**
- * Parse the topology with the specified [id].
- */
- override suspend fun construct(coroutineScope: CoroutineScope, clock: Clock): Environment {
- val nodes = mutableListOf<SimBareMetalDriver>()
+
+ public override fun read(): List<MachineDef> {
+ val nodes = mutableListOf<MachineDef>()
val random = Random(0)
for (machine in fetchMachines(id)) {
@@ -85,36 +73,17 @@ public class TopologyParser(private val collection: MongoCollection<Document>, p
val energyConsumptionW = machine.getList("cpus", Document::class.java).sumBy { it.getInteger("energyConsumptionW") }.toDouble()
nodes.add(
- SimBareMetalDriver(
- coroutineScope,
- clock,
+ MachineDef(
UUID(random.nextLong(), random.nextLong()),
"node-$clusterId-$position",
- mapOf(NODE_CLUSTER to clusterId),
+ mapOf("cluster" to clusterId),
SimMachineModel(processors, memoryUnits),
LinearPowerModel(2 * energyConsumptionW, .5)
)
)
}
- val provisioningService = SimpleProvisioningService()
- coroutineScope.launch {
- for (node in nodes) {
- provisioningService.create(node)
- }
- }
-
- val serviceRegistry = ServiceRegistry().put(ProvisioningService, provisioningService)
-
- val platform = Platform(
- UUID.randomUUID(),
- "opendc-platform",
- listOf(
- Zone(UUID.randomUUID(), "zone", serviceRegistry)
- )
- )
-
- return Environment(fetchName(id), null, listOf(platform))
+ return nodes
}
override fun close() {}
diff --git a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/WebExperimentMonitor.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/WebExperimentMonitor.kt
index fe814c76..a8ac6c10 100644
--- a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/WebExperimentMonitor.kt
+++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/WebExperimentMonitor.kt
@@ -27,10 +27,9 @@ import org.opendc.compute.api.Server
import org.opendc.compute.api.ServerState
import org.opendc.compute.service.ComputeServiceEvent
import org.opendc.compute.service.driver.Host
+import org.opendc.compute.service.driver.HostState
import org.opendc.experiments.capelin.monitor.ExperimentMonitor
import org.opendc.experiments.capelin.telemetry.HostEvent
-import org.opendc.metal.Node
-import org.opendc.metal.NodeState
import kotlin.math.max
/**
@@ -38,7 +37,7 @@ import kotlin.math.max
*/
public class WebExperimentMonitor : ExperimentMonitor {
private val logger = KotlinLogging.logger {}
- private val currentHostEvent = mutableMapOf<Node, HostEvent>()
+ private val currentHostEvent = mutableMapOf<Host, HostEvent>()
private var startTime = -1L
override fun reportVmStateChange(time: Long, server: Server, newState: ServerState) {
@@ -50,12 +49,8 @@ public class WebExperimentMonitor : ExperimentMonitor {
}
}
- override fun reportHostStateChange(
- time: Long,
- driver: Host,
- host: Node
- ) {
- logger.debug { "Host ${host.uid} changed state ${host.state} [$time]" }
+ override fun reportHostStateChange(time: Long, host: Host, newState: HostState) {
+ logger.debug { "Host ${host.uid} changed state $newState [$time]" }
val previousEvent = currentHostEvent[host]
@@ -84,9 +79,9 @@ public class WebExperimentMonitor : ExperimentMonitor {
)
}
- private val lastPowerConsumption = mutableMapOf<Node, Double>()
+ private val lastPowerConsumption = mutableMapOf<Host, Double>()
- override fun reportPowerConsumption(host: Node, draw: Double) {
+ override fun reportPowerConsumption(host: Host, draw: Double) {
lastPowerConsumption[host] = draw
}
@@ -99,7 +94,7 @@ public class WebExperimentMonitor : ExperimentMonitor {
cpuUsage: Double,
cpuDemand: Double,
numberOfDeployedImages: Int,
- host: Node,
+ host: Host,
duration: Long
) {
val previousEvent = currentHostEvent[host]
@@ -117,7 +112,7 @@ public class WebExperimentMonitor : ExperimentMonitor {
cpuUsage,
cpuDemand,
lastPowerConsumption[host] ?: 200.0,
- host.flavor.cpuCount
+ host.model.cpuCount
)
currentHostEvent[host] = event
@@ -135,7 +130,7 @@ public class WebExperimentMonitor : ExperimentMonitor {
cpuUsage,
cpuDemand,
lastPowerConsumption[host] ?: 200.0,
- host.flavor.cpuCount
+ host.model.cpuCount
)
currentHostEvent[host] = event
@@ -155,7 +150,7 @@ public class WebExperimentMonitor : ExperimentMonitor {
cpuUsage,
cpuDemand,
lastPowerConsumption[host] ?: 200.0,
- host.flavor.cpuCount
+ host.model.cpuCount
)
currentHostEvent[host] = event
@@ -164,7 +159,7 @@ public class WebExperimentMonitor : ExperimentMonitor {
}
private var hostAggregateMetrics: AggregateHostMetrics = AggregateHostMetrics()
- private val hostMetrics: MutableMap<Node, HostMetrics> = mutableMapOf()
+ private val hostMetrics: MutableMap<Host, HostMetrics> = mutableMapOf()
private fun processHostEvent(event: HostEvent) {
val slices = event.duration / SLICE_LENGTH
@@ -175,14 +170,14 @@ public class WebExperimentMonitor : ExperimentMonitor {
hostAggregateMetrics.totalOvercommittedBurst + event.overcommissionedBurst,
hostAggregateMetrics.totalInterferedBurst + event.interferedBurst,
hostAggregateMetrics.totalPowerDraw + (slices * (event.powerDraw / 12)),
- hostAggregateMetrics.totalFailureSlices + if (event.node.state != NodeState.ACTIVE) slices.toLong() else 0,
- hostAggregateMetrics.totalFailureVmSlices + if (event.node.state != NodeState.ACTIVE) event.vmCount * slices.toLong() else 0
+ hostAggregateMetrics.totalFailureSlices + if (event.host.state != HostState.UP) slices else 0,
+ hostAggregateMetrics.totalFailureVmSlices + if (event.host.state != HostState.UP) event.vmCount * slices else 0
)
- hostMetrics.compute(event.node) { _, prev ->
+ hostMetrics.compute(event.host) { _, prev ->
HostMetrics(
- (event.cpuUsage.takeIf { event.node.state == NodeState.ACTIVE } ?: 0.0) + (prev?.cpuUsage ?: 0.0),
- (event.cpuDemand.takeIf { event.node.state == NodeState.ACTIVE } ?: 0.0) + (prev?.cpuDemand ?: 0.0),
+ (event.cpuUsage.takeIf { event.host.state == HostState.UP } ?: 0.0) + (prev?.cpuUsage ?: 0.0),
+ (event.cpuDemand.takeIf { event.host.state == HostState.UP } ?: 0.0) + (prev?.cpuDemand ?: 0.0),
event.vmCount + (prev?.vmCount ?: 0),
1 + (prev?.count ?: 0)
)
diff --git a/simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt b/simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt
index 4207cdfd..52bf3db5 100644
--- a/simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt
+++ b/simulator/opendc-workflows/src/test/kotlin/org/opendc/workflows/service/StageWorkflowSchedulerIntegrationTest.kt
@@ -25,7 +25,6 @@
package org.opendc.workflows.service
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
@@ -38,10 +37,9 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
import org.opendc.compute.service.ComputeService
import org.opendc.compute.service.scheduler.NumberOfActiveServersAllocationPolicy
-import org.opendc.compute.simulator.SimHostProvisioner
+import org.opendc.compute.simulator.SimHost
import org.opendc.format.environment.sc18.Sc18EnvironmentReader
import org.opendc.format.trace.gwf.GwfTraceReader
-import org.opendc.metal.service.ProvisioningService
import org.opendc.simulator.compute.SimSpaceSharedHypervisorProvider
import org.opendc.simulator.utils.DelayControllerClockAdapter
import org.opendc.trace.core.EventTracer
@@ -72,24 +70,25 @@ internal class StageWorkflowSchedulerIntegrationTest {
val clock = DelayControllerClockAdapter(testScope)
val tracer = EventTracer(clock)
- val schedulerAsync = testScope.async {
- val environment = Sc18EnvironmentReader(object {}.javaClass.getResourceAsStream("/environment.json"))
- .use { it.construct(testScope, clock) }
-
- val bareMetal = environment.platforms[0].zones[0].services[ProvisioningService]
-
- // Wait for the bare metal nodes to be spawned
- delay(10)
+ val scheduler = let {
+ val hosts = Sc18EnvironmentReader(object {}.javaClass.getResourceAsStream("/environment.json"))
+ .use { it.read() }
+ .map { def ->
+ SimHost(
+ def.uid,
+ def.name,
+ def.model,
+ def.meta,
+ testScope.coroutineContext,
+ clock,
+ SimSpaceSharedHypervisorProvider()
+ )
+ }
- val provisioner = SimHostProvisioner(testScope.coroutineContext, bareMetal, SimSpaceSharedHypervisorProvider())
- val hosts = provisioner.provisionAll()
val compute = ComputeService(testScope.coroutineContext, clock, tracer, NumberOfActiveServersAllocationPolicy(), schedulingQuantum = 1000)
hosts.forEach { compute.addHost(it) }
- // Wait for the hypervisors to be spawned
- delay(10)
-
StageWorkflowService(
testScope,
clock,
@@ -104,7 +103,6 @@ internal class StageWorkflowSchedulerIntegrationTest {
}
testScope.launch {
- val scheduler = schedulerAsync.await()
scheduler.events
.onEach { event ->
when (event) {
@@ -119,7 +117,6 @@ internal class StageWorkflowSchedulerIntegrationTest {
testScope.launch {
val reader = GwfTraceReader(object {}.javaClass.getResourceAsStream("/trace.gwf"))
- val scheduler = schedulerAsync.await()
while (reader.hasNext()) {
val (time, job) = reader.next()
diff --git a/simulator/settings.gradle.kts b/simulator/settings.gradle.kts
index 7a82adcd..41cdf773 100644
--- a/simulator/settings.gradle.kts
+++ b/simulator/settings.gradle.kts
@@ -26,7 +26,6 @@ include(":opendc-core")
include(":opendc-compute:opendc-compute-api")
include(":opendc-compute:opendc-compute-service")
include(":opendc-compute:opendc-compute-simulator")
-include(":opendc-metal")
include(":opendc-workflows")
include(":opendc-format")
include(":opendc-experiments:opendc-experiments-sc18")