summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2020-10-02 20:57:51 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2020-10-02 20:59:57 +0200
commitac7016c4c5f15bf20b21e7d34e93d8b963aab231 (patch)
tree0e2ab55237371642940e1050232c4bd1e09d448f
parent76c5d27618181c4ec9cf86085c65b5e69f5f9109 (diff)
Implement BareMetalDriver using SimMachine
This change creates an implementation of the BareMetalDriver interface using the simulation logic of SimMachine. This implementation will eventually replace the SimpleBareMetalDriver implementation.
-rw-r--r--simulator/opendc-compute/build.gradle.kts1
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/execution/ServerContext.kt4
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/image/SimWorkloadImage.kt45
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriver.kt229
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriver.kt3
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimpleVirtDriver.kt2
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/VirtDriver.kt2
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/SimpleVirtProvisioningService.kt4
-rw-r--r--simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/VirtProvisioningService.kt2
-rw-r--r--simulator/opendc-compute/src/test/kotlin/org/opendc/compute/core/image/FlopsApplicationImageTest.kt4
-rw-r--r--simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriverTest.kt90
-rw-r--r--simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt4
-rw-r--r--simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt33
-rw-r--r--simulator/opendc-compute/src/test/kotlin/org/opendc/compute/virt/HypervisorTest.kt4
14 files changed, 402 insertions, 25 deletions
diff --git a/simulator/opendc-compute/build.gradle.kts b/simulator/opendc-compute/build.gradle.kts
index ea82faa5..94af7861 100644
--- a/simulator/opendc-compute/build.gradle.kts
+++ b/simulator/opendc-compute/build.gradle.kts
@@ -31,6 +31,7 @@ dependencies {
api(project(":opendc-core"))
implementation(project(":opendc-utils"))
implementation("io.github.microutils:kotlin-logging:1.7.9")
+ implementation(project(":opendc-simulator:opendc-simulator-compute"))
testImplementation(project(":opendc-simulator:opendc-simulator-core"))
testRuntimeOnly("org.slf4j:slf4j-simple:${Library.SLF4J}")
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/execution/ServerContext.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/execution/ServerContext.kt
index 9674c98d..82cec00a 100644
--- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/execution/ServerContext.kt
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/execution/ServerContext.kt
@@ -66,7 +66,7 @@ public interface ServerContext {
* @param triggerMode The trigger condition to resume execution.
*/
public suspend fun run(slice: Slice, triggerMode: TriggerMode = TriggerMode.FIRST): Unit =
- select<Unit> { onRun(slice, triggerMode).invoke {} }
+ select { onRun(slice, triggerMode).invoke {} }
/**
* Ask the processors cores to run the specified [batch] of work slices and suspend execution until the trigger
@@ -88,7 +88,7 @@ public interface ServerContext {
batch: Sequence<Slice>,
triggerMode: TriggerMode = TriggerMode.FIRST,
merge: (Slice, Slice) -> Slice = { _, r -> r }
- ): Unit = select<Unit> { onRun(batch, triggerMode, merge).invoke {} }
+ ): Unit = select { onRun(batch, triggerMode, merge).invoke {} }
/**
* Ask the processor cores to run the specified [slice] and select when the trigger condition is met as specified
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/image/SimWorkloadImage.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/image/SimWorkloadImage.kt
new file mode 100644
index 00000000..7caedf6d
--- /dev/null
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/image/SimWorkloadImage.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.core.image
+
+import org.opendc.compute.core.execution.ServerContext
+import org.opendc.core.resource.TagContainer
+import org.opendc.simulator.compute.workload.SimWorkload
+import java.util.*
+
+/**
+ * An application [Image] that runs a [SimWorkload].
+ *
+ * @property uid The unique identifier of this image.
+ * @property name The name of this image.
+ * @property tags The tags attached to the image.
+ * @property workload The workload to run for this image.
+ */
+public data class SimWorkloadImage(
+ public override val uid: UUID,
+ public override val name: String,
+ public override val tags: TagContainer,
+ public val workload: SimWorkload
+) : Image {
+ override suspend fun invoke(ctx: ServerContext): Unit = TODO()
+}
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriver.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriver.kt
new file mode 100644
index 00000000..e9346a6c
--- /dev/null
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriver.kt
@@ -0,0 +1,229 @@
+/*
+ * 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.metal.driver
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.Flow
+import org.opendc.compute.core.Flavor
+import org.opendc.compute.core.Server
+import org.opendc.compute.core.ServerEvent
+import org.opendc.compute.core.ServerState
+import org.opendc.compute.core.execution.ShutdownException
+import org.opendc.compute.core.image.EmptyImage
+import org.opendc.compute.core.image.Image
+import org.opendc.compute.core.image.SimWorkloadImage
+import org.opendc.compute.metal.Node
+import org.opendc.compute.metal.NodeEvent
+import org.opendc.compute.metal.NodeState
+import org.opendc.compute.metal.power.ConstantPowerModel
+import org.opendc.core.power.PowerModel
+import org.opendc.core.services.ServiceRegistry
+import org.opendc.simulator.compute.SimMachine
+import org.opendc.simulator.compute.SimMachineModel
+import org.opendc.utils.flow.EventFlow
+import org.opendc.utils.flow.StateFlow
+import java.time.Clock
+import java.util.UUID
+import kotlin.random.Random
+
+/**
+ * A basic implementation of the [BareMetalDriver] that simulates an [Image] running on a bare-metal machine.
+ *
+ * @param coroutineScope The [CoroutineScope] the driver runs in.
+ * @param clock The virtual clock to keep track of time.
+ * @param uid The unique identifier of the machine.
+ * @param name An optional name of the machine.
+ * @param metadata The initial metadata of the node.
+ * @param machine The machine model to simulate.
+ * @param powerModel The power model of this machine.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+public class SimBareMetalDriver(
+ private val coroutineScope: CoroutineScope,
+ private val clock: Clock,
+ uid: UUID,
+ name: String,
+ metadata: Map<String, Any>,
+ machine: SimMachineModel,
+ powerModel: PowerModel<SimBareMetalDriver> = ConstantPowerModel(0.0)
+) : BareMetalDriver {
+ /**
+ * The flavor that corresponds to this machine.
+ */
+ private val flavor = Flavor(
+ machine.cpus.size,
+ machine.memory.map { it.size }.sum()
+ )
+
+ /**
+ * The events of the machine.
+ */
+ private val events = EventFlow<NodeEvent>()
+
+ /**
+ * The machine state.
+ */
+ private val nodeState =
+ StateFlow(Node(uid, name, metadata + ("driver" to this), NodeState.SHUTOFF, EmptyImage, null, events))
+
+ override val node: Flow<Node> = nodeState
+
+ override val usage: Flow<Double>
+ get() = this.machine.usage
+
+ override val powerDraw: Flow<Double> = powerModel(this)
+
+ /**
+ * The internal random instance.
+ */
+ private val random = Random(uid.leastSignificantBits xor uid.mostSignificantBits)
+
+ /**
+ * The [SimMachine] we use to run the workload.
+ */
+ private val machine = SimMachine(coroutineScope, clock, machine)
+
+ /**
+ * The [Job] that runs the simulated workload.
+ */
+ private var job: Job? = null
+
+ /**
+ * The event stream to publish to for the server.
+ */
+ private var serverEvents: EventFlow<ServerEvent>? = null
+
+ override suspend fun init(): Node {
+ return nodeState.value
+ }
+
+ override suspend fun start(): Node {
+ val node = nodeState.value
+ if (node.state != NodeState.SHUTOFF) {
+ return node
+ }
+
+ val events = EventFlow<ServerEvent>()
+ serverEvents = events
+ val server = Server(
+ UUID(random.nextLong(), random.nextLong()),
+ node.name,
+ emptyMap(),
+ flavor,
+ node.image,
+ ServerState.BUILD,
+ ServiceRegistry().put(BareMetalDriver, this@SimBareMetalDriver),
+ events
+ )
+
+ job = coroutineScope.launch {
+ delay(1) // TODO Introduce boot time
+ initMachine()
+ try {
+ machine.run((node.image as SimWorkloadImage).workload)
+ exitMachine(null)
+ } catch (_: CancellationException) {
+ // Ignored
+ } catch (cause: Throwable) {
+ exitMachine(cause)
+ }
+ }
+
+ setNode(node.copy(state = NodeState.BOOT, server = server))
+ return nodeState.value
+ }
+
+ private fun initMachine() {
+ val server = nodeState.value.server?.copy(state = ServerState.ACTIVE)
+ setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
+ }
+
+ private fun exitMachine(cause: Throwable?) {
+ val newServerState =
+ if (cause == null || (cause is ShutdownException && cause.cause == null))
+ ServerState.SHUTOFF
+ else
+ ServerState.ERROR
+ val newNodeState =
+ if (cause == null || (cause is ShutdownException && cause.cause != null))
+ nodeState.value.state
+ else
+ NodeState.ERROR
+ val server = nodeState.value.server?.copy(state = newServerState)
+ setNode(nodeState.value.copy(state = newNodeState, server = server))
+
+ serverEvents?.close()
+ serverEvents = null
+ }
+
+ override suspend fun stop(): Node {
+ val node = nodeState.value
+ if (node.state == NodeState.SHUTOFF) {
+ return node
+ }
+
+ job?.cancelAndJoin()
+ setNode(node.copy(state = NodeState.SHUTOFF, server = null))
+ return node
+ }
+
+ override suspend fun reboot(): Node {
+ stop()
+ return start()
+ }
+
+ override suspend fun setImage(image: Image): Node {
+ setNode(nodeState.value.copy(image = image))
+ return nodeState.value
+ }
+
+ override suspend fun refresh(): Node = nodeState.value
+
+ private fun setNode(value: Node) {
+ val field = nodeState.value
+ if (field.state != value.state) {
+ events.emit(NodeEvent.StateChanged(value, field.state))
+ }
+
+ if (field.server != null && value.server != null && field.server.state != value.server.state) {
+ serverEvents?.emit(ServerEvent.StateChanged(value.server, field.server.state))
+ }
+
+ nodeState.value = value
+ }
+
+ override val scope: CoroutineScope
+ get() = coroutineScope
+
+ override suspend fun fail() {
+ val server = nodeState.value.server?.copy(state = ServerState.ERROR)
+ setNode(nodeState.value.copy(state = NodeState.ERROR, server = server))
+ }
+
+ override suspend fun recover() {
+ val server = nodeState.value.server?.copy(state = ServerState.ACTIVE)
+ setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
+ }
+
+ override fun toString(): String = "SimBareMetalDriver(node = ${nodeState.value.uid})"
+}
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriver.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriver.kt
index 817528f6..c4897197 100644
--- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriver.kt
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriver.kt
@@ -92,7 +92,8 @@ public class SimpleBareMetalDriver(
/**
* The flavor that corresponds to this machine.
*/
- private val flavor = Flavor(cpus.size, memoryUnits.map { it.size }.sum())
+ private val flavor =
+ Flavor(cpus.size, memoryUnits.map { it.size }.sum())
/**
* The current active server context.
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimpleVirtDriver.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimpleVirtDriver.kt
index fb3d5f84..d581e651 100644
--- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimpleVirtDriver.kt
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimpleVirtDriver.kt
@@ -105,7 +105,7 @@ public class SimpleVirtDriver(
override suspend fun spawn(
name: String,
image: Image,
- flavor: Flavor
+ flavor: org.opendc.compute.core.Flavor
): Server {
val requiredMemory = flavor.memorySize
if (availableMemory - requiredMemory < 0) {
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/VirtDriver.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/VirtDriver.kt
index 9663f4da..54728eb6 100644
--- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/VirtDriver.kt
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/VirtDriver.kt
@@ -51,7 +51,7 @@ public interface VirtDriver {
public suspend fun spawn(
name: String,
image: Image,
- flavor: Flavor
+ flavor: org.opendc.compute.core.Flavor
): Server
public companion object Key : AbstractServiceKey<VirtDriver>(UUID.randomUUID(), "virtual-driver")
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/SimpleVirtProvisioningService.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/SimpleVirtProvisioningService.kt
index 3141529f..f021d3f0 100644
--- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/SimpleVirtProvisioningService.kt
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/SimpleVirtProvisioningService.kt
@@ -119,7 +119,7 @@ public class SimpleVirtProvisioningService(
override suspend fun deploy(
name: String,
image: Image,
- flavor: Flavor
+ flavor: org.opendc.compute.core.Flavor
): Server {
eventFlow.emit(
VirtProvisioningEvent.MetricsAvailable(
@@ -373,7 +373,7 @@ public class SimpleVirtProvisioningService(
public data class ImageView(
public val name: String,
public val image: Image,
- public val flavor: Flavor,
+ public val flavor: org.opendc.compute.core.Flavor,
public val continuation: Continuation<Server>,
public var server: Server? = null
)
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/VirtProvisioningService.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/VirtProvisioningService.kt
index 7ed577c4..13dfd640 100644
--- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/VirtProvisioningService.kt
+++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/service/VirtProvisioningService.kt
@@ -58,7 +58,7 @@ public interface VirtProvisioningService {
public suspend fun deploy(
name: String,
image: Image,
- flavor: Flavor
+ flavor: org.opendc.compute.core.Flavor
): Server
/**
diff --git a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/core/image/FlopsApplicationImageTest.kt b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/core/image/FlopsApplicationImageTest.kt
index 309dceb8..8870f138 100644
--- a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/core/image/FlopsApplicationImageTest.kt
+++ b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/core/image/FlopsApplicationImageTest.kt
@@ -1,7 +1,5 @@
/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
+ * Copyright (c) 2020 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriverTest.kt b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriverTest.kt
new file mode 100644
index 00000000..584dcef4
--- /dev/null
+++ b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimBareMetalDriverTest.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.metal.driver
+
+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.opendc.compute.core.ServerEvent
+import org.opendc.compute.core.ServerState
+import org.opendc.compute.core.image.SimWorkloadImage
+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: ServerState = ServerState.BUILD
+ var finalTime = 0L
+
+ testScope.launch {
+ val driver = SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
+ val image = SimWorkloadImage(UUID.randomUUID(), "<unnamed>", emptyMap(), SimFlopsWorkload(4_000, 2, utilization = 1.0))
+
+ // Batch driver commands
+ withContext(coroutineContext) {
+ driver.init()
+ driver.setImage(image)
+ val server = driver.start().server!!
+ server.events.collect { event ->
+ when (event) {
+ is ServerEvent.StateChanged -> {
+ finalState = event.server.state
+ finalTime = clock.millis()
+ }
+ }
+ }
+ }
+ }
+
+ testScope.advanceUntilIdle()
+ assertEquals(ServerState.SHUTOFF, finalState)
+ assertEquals(1001, finalTime)
+ }
+}
diff --git a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt
index 9c9dc864..23c9408d 100644
--- a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt
+++ b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt
@@ -52,9 +52,9 @@ internal class SimpleBareMetalDriverTest {
var finalState: ServerState = ServerState.BUILD
testScope.launch {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
- val cpus = List(4) { ProcessingUnit(cpuNode, it, 2400.0) }
+ val cpus = List(4) { ProcessingUnit(cpuNode, it, 2000.0) }
val driver = SimpleBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
- val image = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1_000, 2)
+ val image = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 4_000, 2, utilization = 1.0)
// Batch driver commands
withContext(coroutineContext) {
diff --git a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt
index 91d4787c..6f13e557 100644
--- a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt
+++ b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt
@@ -27,11 +27,15 @@ 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.core.ProcessingNode
-import org.opendc.compute.core.ProcessingUnit
-import org.opendc.compute.core.image.FlopsApplicationImage
-import org.opendc.compute.metal.driver.SimpleBareMetalDriver
+import org.opendc.compute.core.image.SimWorkloadImage
+import org.opendc.compute.metal.driver.SimBareMetalDriver
+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
@@ -40,20 +44,29 @@ import java.util.UUID
*/
@OptIn(ExperimentalCoroutinesApi::class)
internal class SimpleProvisioningServiceTest {
+ private lateinit var machineModel: SimMachineModel
+
+ @BeforeEach
+ fun setUp() {
+ val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
+
+ machineModel = SimMachineModel(
+ cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 2000.0) },
+ memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ )
+ }
+
/**
* A basic smoke test.
*/
@Test
- fun smoke() {
+ fun testSmoke() {
val testScope = TestCoroutineScope()
val clock = DelayControllerClockAdapter(testScope)
testScope.launch {
- val image = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1000, 2)
-
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
- val cpus = List(4) { ProcessingUnit(cpuNode, it, 2400.0) }
- val driver = SimpleBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
+ val image = SimWorkloadImage(UUID.randomUUID(), "<unnamed>", emptyMap(), SimFlopsWorkload(1000, 2))
+ val driver = SimBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), machineModel)
val provisioner = SimpleProvisioningService()
provisioner.create(driver)
diff --git a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/virt/HypervisorTest.kt b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/virt/HypervisorTest.kt
index 68efb1a3..369b9538 100644
--- a/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/virt/HypervisorTest.kt
+++ b/simulator/opendc-compute/src/test/kotlin/org/opendc/compute/virt/HypervisorTest.kt
@@ -75,7 +75,7 @@ internal class HypervisorTest {
delay(5)
- val flavor = Flavor(1, 0)
+ val flavor = org.opendc.compute.core.Flavor(1, 0)
val vmDriver = metalDriver.refresh().server!!.services[VirtDriver]
vmDriver.events.onEach { println(it) }.launchIn(this)
val vmA = vmDriver.spawn("a", workloadA, flavor)
@@ -140,7 +140,7 @@ internal class HypervisorTest {
delay(5)
- val flavor = Flavor(2, 0)
+ val flavor = org.opendc.compute.core.Flavor(2, 0)
val vmDriver = metalDriver.refresh().server!!.services[VirtDriver]
vmDriver.events
.onEach { event ->