summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2020-02-14 00:53:24 +0100
committerFabian Mastenbroek <mail.fabianm@gmail.com>2020-02-14 00:53:24 +0100
commit3fc32c0b6f02d245a544aaaa061094231830f661 (patch)
treecf55b824a1d6746f7d218c39f0db1cc53a662edb
parentd40eae0264236be3a9d34f39a63adde8a9b47a57 (diff)
refactor: Remodel workloads and compute resource
This change remodels our model for workloads and compute resources in order to support VM/container functionality where multiple workloads run on a single machine. In particular, we make the following changes: - Move the compute-related source code into the `opendc-compute` module. - Change from application-based model to image-based model, where the image has exclusive access over the machine, instead of applications that share the machine. We may model in the future again applications/operating system, but at the moment, we do not need this granularity, given that the workload traces can be simulated using VMs.
-rw-r--r--opendc/opendc-compute/build.gradle.kts41
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt42
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt42
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt64
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt55
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/Protocol.kt143
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt46
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt40
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt36
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt57
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt51
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/Protocol.kt77
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/ServerMonitor.kt41
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt63
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/PowerState.kt40
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt58
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriver.kt138
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/Protocol.kt146
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/Allocation.kt37
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt55
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt40
-rw-r--r--opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriverTest.kt70
-rw-r--r--settings.gradle.kts1
23 files changed, 1383 insertions, 0 deletions
diff --git a/opendc/opendc-compute/build.gradle.kts b/opendc/opendc-compute/build.gradle.kts
new file mode 100644
index 00000000..09c904f2
--- /dev/null
+++ b/opendc/opendc-compute/build.gradle.kts
@@ -0,0 +1,41 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * 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 = "Cloud computing fabric simulation model"
+
+/* Build configuration */
+plugins {
+ `kotlin-library-convention`
+}
+
+dependencies {
+ implementation(kotlin("stdlib"))
+ api(project(":odcsim:odcsim-api"))
+ api(project(":opendc:opendc-core"))
+
+ testRuntimeOnly(project(":odcsim:odcsim-engine-omega"))
+ testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
+ testImplementation("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}")
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt
new file mode 100644
index 00000000..0094704a
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt
@@ -0,0 +1,42 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core
+
+/**
+ * (Virtual) hardware configuration of a server.
+ */
+public data class Flavor(
+ /**
+ * The processing units of this machine.
+ */
+ public val cpus: List<ProcessingUnit>,
+
+ /**
+ * Key and value pairs that can be used to describe the specification of the server which is more than just about
+ * CPU, disk and RAM. For example, it can be used to indicate that the server created by this flavor has PCI
+ * devices, etc.
+ */
+ public val details: Map<String, Any> = emptyMap()
+)
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt
new file mode 100644
index 00000000..945b7061
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt
@@ -0,0 +1,42 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core
+
+/**
+ * A processing unit of a compute resource, either virtual or physical.
+ *
+ * @property vendor The vendor string of the cpu.
+ * @property modelName The name of the cpu model.
+ * @property arch The architecture of the CPU.
+ * @property clockRate The clock speed of the cpu in MHz.
+ * @property cores The number of logical cores in the cpu.
+ */
+public data class ProcessingUnit(
+ public val vendor: String,
+ public val modelName: String,
+ public val arch: String,
+ public val clockRate: Double,
+ public val cores: Int
+)
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt
new file mode 100644
index 00000000..0dc1562c
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt
@@ -0,0 +1,64 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core
+
+import com.atlarge.opendc.compute.core.image.Image
+import com.atlarge.opendc.compute.metal.Node
+import com.atlarge.opendc.core.Identity
+import java.util.UUID
+
+/**
+ * A server instance that is running on some physical or virtual machine.
+ */
+public data class Server(
+ /**
+ * The unique identifier of the server.
+ */
+ public override val uid: UUID,
+
+ /**
+ * The optional name of the server.
+ */
+ public override val name: String,
+
+ /**
+ * The hardware configuration of the server.
+ */
+ public val flavor: Flavor,
+
+ /**
+ * The image running on the server.
+ */
+ public val image: Image,
+
+ /**
+ * The last known state of the server.
+ */
+ public val state: ServerState
+
+) : Identity {
+ override fun hashCode(): Int = uid.hashCode()
+ override fun equals(other: Any?): Boolean = other is Node && uid == other.uid
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt
new file mode 100644
index 00000000..27372a5e
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt
@@ -0,0 +1,55 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core
+
+/**
+ * An enumeration describing the possible states of a server.
+ */
+public enum class ServerState {
+ /**
+ * The server has not yet finished the original build process.
+ */
+ BUILD,
+
+ /**
+ * The server was powered down by the user.
+ */
+ SHUTOFF,
+
+ /**
+ * The server is active and running.
+ */
+ ACTIVE,
+
+ /**
+ * The server is in error.
+ */
+ ERROR,
+
+ /**
+ * The state of the server is unknown.
+ */
+ UNKNOWN,
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/Protocol.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/Protocol.kt
new file mode 100644
index 00000000..1e4fa0fb
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/Protocol.kt
@@ -0,0 +1,143 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.execution
+
+import com.atlarge.odcsim.ReceivePort
+import com.atlarge.odcsim.SendPort
+import com.atlarge.odcsim.processContext
+import com.atlarge.opendc.compute.core.Server
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+
+/**
+ * Request that are accepted by a [ServerContext] instance.
+ */
+public sealed class ServerRequest {
+ /**
+ * Request the context to be initialized.
+ */
+ public object Initialize : ServerRequest()
+
+ /**
+ * Request for each core the specified amount of cpu time to run from the server
+ */
+ public data class Run(public val req: LongArray) : ServerRequest()
+
+ /**
+ * Terminate the execution of the server.
+ */
+ public data class Exit(public val cause: Throwable? = null) : ServerRequest()
+}
+
+/**
+ * Messages sent in response to [ServerRequest] objects.
+ */
+public sealed class ServerResponse {
+ /**
+ * The server that sent this response.
+ */
+ public abstract val server: Server
+
+ /**
+ * Indicate that this request was processed successfully.
+ */
+ public data class Ok(public override val server: Server) : ServerResponse()
+}
+
+/**
+ * Serialize the specified [ServerManagementContext] instance in order to safely send this object across logical
+ * processes.
+ */
+public suspend fun ServerManagementContext.serialize(): ServerManagementContext {
+ val ctx = processContext
+ val input = ctx.open<ServerRequest>()
+ val output = ctx.open<ServerResponse>()
+
+ ctx.launch {
+ val outlet = processContext.connect(output.send)
+ val inlet = processContext.listen(input.receive)
+
+ while (isActive) {
+ when (val msg = inlet.receive()) {
+ is ServerRequest.Initialize -> {
+ init()
+ outlet.send(ServerResponse.Ok(server))
+ }
+ is ServerRequest.Run -> {
+ run(msg.req)
+ outlet.send(ServerResponse.Ok(server))
+ }
+ is ServerRequest.Exit -> {
+ exit(msg.cause)
+ outlet.send(ServerResponse.Ok(server))
+ }
+ }
+ }
+ }
+
+ return object : ServerManagementContext {
+ private lateinit var inlet: ReceivePort<ServerResponse>
+ private lateinit var outlet: SendPort<ServerRequest>
+
+ override var server: Server = this@serialize.server
+
+ override suspend fun run(req: LongArray) {
+ outlet.send(ServerRequest.Run(req))
+
+ when (val res = inlet.receive()) {
+ is ServerResponse.Ok -> {
+ server = res.server
+ }
+ }
+ }
+
+ override suspend fun exit(cause: Throwable?) {
+ outlet.send(ServerRequest.Exit(cause))
+
+ when (val res = inlet.receive()) {
+ is ServerResponse.Ok -> {
+ server = res.server
+ }
+ }
+ }
+
+ override suspend fun init() {
+ if (!this::outlet.isInitialized) {
+ outlet = processContext.connect(input.send)
+ }
+
+ if (!this::inlet.isInitialized) {
+ inlet = processContext.listen(output.receive)
+ }
+
+ outlet.send(ServerRequest.Initialize)
+ when (val res = inlet.receive()) {
+ is ServerResponse.Ok -> {
+ server = res.server
+ }
+ }
+ }
+ }
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt
new file mode 100644
index 00000000..057ed118
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt
@@ -0,0 +1,46 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.execution
+
+import com.atlarge.opendc.compute.core.Server
+import com.atlarge.opendc.compute.core.image.Image
+
+/**
+ * Represents the execution context in which an bootable [Image] runs on a [Server].
+ */
+public interface ServerContext {
+ /**
+ * The server on which the image runs.
+ */
+ public val server: Server
+
+ /**
+ * Request for each core the specified amount of cpu time to run from the server and wait until all the threads have
+ * finished processing. If none of the cores are non-zero, the method will return immediately.
+ *
+ * @param req An array specifying for each core the amount of cpu time to request.
+ */
+ public suspend fun run(req: LongArray)
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt
new file mode 100644
index 00000000..5a9b725b
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt
@@ -0,0 +1,40 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.execution
+
+/**
+ * An extended [ServerContext] providing several methods for managing the execution context.
+ */
+public interface ServerManagementContext : ServerContext {
+ /**
+ * Initialize the management context.
+ */
+ public suspend fun init()
+
+ /**
+ * Terminate the execution of the server.
+ */
+ public suspend fun exit(cause: Throwable? = null)
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt
new file mode 100644
index 00000000..a51e55f9
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt
@@ -0,0 +1,36 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.image
+
+import com.atlarge.opendc.compute.core.execution.ServerContext
+
+/**
+ * An empty boot disk [Image] that exits immediately on start.
+ */
+object EmptyImage : Image {
+ override val details: Map<String, Any> = emptyMap()
+
+ override suspend fun invoke(ctx: ServerContext) {}
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt
new file mode 100644
index 00000000..4519dc49
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt
@@ -0,0 +1,57 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.image
+
+import com.atlarge.opendc.compute.core.execution.ServerContext
+import kotlin.math.min
+
+/**
+ * An application [Image] that models applications performing a static number of floating point operations ([flops]) on
+ * a compute resource.
+ *
+ * @property flops The number of floating point operations to perform for this task.
+ * @property cores The number of cores that the image is able to utilize.
+ * @property utilization A model of the CPU utilization of the application.
+ * @property details The details of this image.
+ */
+class FlopsApplicationImage(
+ public val flops: Long,
+ public val cores: Int,
+ public val utilization: Double = 0.8,
+ public override val details: Map<String, Any> = emptyMap()
+) : Image {
+ init {
+ require(flops >= 0) { "Negative number of flops" }
+ }
+
+ /**
+ * Execute the runtime behavior based on a number of floating point operations to execute.
+ */
+ override suspend fun invoke(ctx: ServerContext) {
+ val cores = min(this.cores, ctx.server.flavor.cpus.sumBy { it.cores })
+ val req = (flops * (1 / utilization) / cores).toLong()
+ ctx.run(LongArray(cores) { req })
+ }
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt
new file mode 100644
index 00000000..bd4f5648
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt
@@ -0,0 +1,51 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.image
+
+import com.atlarge.opendc.compute.core.execution.ServerContext
+
+/**
+ * An image containing a bootable operating system that can directly be executed by physical or virtual server.
+ *
+ * OpenStack: A collection of files used to create or rebuild a server. Operators provide a number of pre-built OS
+ * images by default. You may also create custom images from cloud servers you have launched. These custom images are
+ * useful for backup purposes or for producing “gold” server images if you plan to deploy a particular server
+ * configuration frequently.
+
+ */
+public interface Image {
+ /**
+ * The details of the image in key/value pairs.
+ */
+ public val details: Map<String, Any>
+
+ /**
+ * Launch the machine image in the specified [ServerContext].
+ *
+ * This method should encapsulate and characterize the runtime behavior of the instance resulting from launching
+ * the image on some machine, in terms of the resource consumption on the machine.
+ */
+ public suspend operator fun invoke(ctx: ServerContext)
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/Protocol.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/Protocol.kt
new file mode 100644
index 00000000..b16c0d59
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/Protocol.kt
@@ -0,0 +1,77 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.monitor
+
+import com.atlarge.odcsim.SendPort
+import com.atlarge.odcsim.processContext
+import com.atlarge.opendc.compute.core.Server
+import com.atlarge.opendc.compute.core.ServerState
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+
+/**
+ * Events emitted by a [Server] instance.
+ */
+public sealed class ServerEvent {
+ /**
+ * The server that emitted this event.
+ */
+ public abstract val server: Server
+
+ /**
+ * A response sent when the bare metal driver has been initialized.
+ */
+ public data class StateChanged(public override val server: Server, public val previousState: ServerState) : ServerEvent()
+}
+
+/**
+ * Serialize the specified [ServerMonitor] instance in order to safely send this object across logical processes.
+ */
+public suspend fun ServerMonitor.serialize(): ServerMonitor {
+ val ctx = processContext
+ val input = ctx.open<ServerEvent>()
+
+ ctx.launch {
+ val inlet = processContext.listen(input.receive)
+
+ while (isActive) {
+ when (val msg = inlet.receive()) {
+ is ServerEvent.StateChanged -> onUpdate(msg.server, msg.previousState)
+ }
+ }
+ }
+
+ return object : ServerMonitor {
+ private var outlet: SendPort<ServerEvent>? = null
+
+ override suspend fun onUpdate(server: Server, previousState: ServerState) {
+ if (outlet == null) {
+ outlet = processContext.connect(input.send)
+ }
+
+ outlet!!.send(ServerEvent.StateChanged(server, previousState))
+ }
+ }
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/ServerMonitor.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/ServerMonitor.kt
new file mode 100644
index 00000000..fbfd0ad6
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/monitor/ServerMonitor.kt
@@ -0,0 +1,41 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.core.monitor
+
+import com.atlarge.opendc.compute.core.Server
+import com.atlarge.opendc.compute.core.ServerState
+
+/**
+ * An interface for monitoring the state of a machine.
+ */
+public interface ServerMonitor {
+ /**
+ * This method is invoked when the state of a machine updates.
+ *
+ * @param server The server which state was updated.
+ * @param previousState The previous state of the server.
+ */
+ public suspend fun onUpdate(server: Server, previousState: ServerState)
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt
new file mode 100644
index 00000000..a43abfe9
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt
@@ -0,0 +1,63 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal
+
+import com.atlarge.opendc.compute.core.Server
+import com.atlarge.opendc.compute.core.image.Image
+import com.atlarge.opendc.core.Identity
+import java.util.UUID
+
+/**
+ * A bare-metal compute node.
+ */
+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,
+
+ /**
+ * The power state of the node.
+ */
+ public val powerState: PowerState,
+
+ /**
+ * The boot image of the node.
+ */
+ public val image: Image,
+
+ /**
+ * The server instance that is running on the node or `null` if no server is running.
+ */
+ public val server: Server?
+) : Identity {
+ override fun hashCode(): Int = uid.hashCode()
+ override fun equals(other: Any?): Boolean = other is Node && uid == other.uid
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/PowerState.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/PowerState.kt
new file mode 100644
index 00000000..5fce3f48
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/PowerState.kt
@@ -0,0 +1,40 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal
+
+/**
+ * The power state of a compute node.
+ */
+public enum class PowerState {
+ /**
+ * Node is powered on.
+ */
+ POWER_ON,
+
+ /**
+ * Node is powered off.
+ */
+ POWER_OFF,
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt
new file mode 100644
index 00000000..1330158e
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt
@@ -0,0 +1,58 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal.driver
+
+import com.atlarge.opendc.compute.core.image.Image
+import com.atlarge.opendc.compute.core.monitor.ServerMonitor
+import com.atlarge.opendc.compute.metal.Node
+import com.atlarge.opendc.compute.metal.PowerState
+
+/**
+ * A driver interface for the management interface of a bare-metal compute node.
+ */
+public interface BareMetalDriver {
+ /**
+ * Initialize the driver.
+ */
+ public suspend fun init(monitor: ServerMonitor): Node
+
+ /**
+ * Update the power state of the compute node.
+ */
+ public suspend fun setPower(powerState: PowerState): 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
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriver.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriver.kt
new file mode 100644
index 00000000..9d984017
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriver.kt
@@ -0,0 +1,138 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal.driver
+
+import com.atlarge.odcsim.processContext
+import com.atlarge.opendc.compute.core.Flavor
+import com.atlarge.opendc.compute.core.Server
+import com.atlarge.opendc.compute.core.ServerState
+import com.atlarge.opendc.compute.core.execution.ServerManagementContext
+import com.atlarge.opendc.compute.core.execution.serialize
+import com.atlarge.opendc.compute.core.image.EmptyImage
+import com.atlarge.opendc.compute.core.image.Image
+import com.atlarge.opendc.compute.core.monitor.ServerMonitor
+import com.atlarge.opendc.compute.metal.Node
+import com.atlarge.opendc.compute.metal.PowerState
+import java.util.UUID
+import kotlin.math.max
+import kotlinx.coroutines.delay
+
+/**
+ * A implementation of the [BareMetalDriver] that simulates an [Image] running on a bare-metal machine, but performs
+ * not actual computation.
+ *
+ * @param uid The unique identifier of the machine.
+ * @param name An optional name of the machine.
+ * @param flavor The hardware configuration of the machine.
+ */
+public class FakeBareMetalDriver(
+ uid: UUID,
+ name: String,
+ private val flavor: Flavor
+) : BareMetalDriver {
+ /**
+ * The monitor to use.
+ */
+ private lateinit var monitor: ServerMonitor
+
+ /**
+ * The machine state.
+ */
+ private var node: Node = Node(uid, name, PowerState.POWER_OFF, EmptyImage, null)
+
+ override suspend fun init(monitor: ServerMonitor): Node {
+ this.monitor = monitor
+ return node
+ }
+
+ override suspend fun setPower(powerState: PowerState): Node {
+ val previousPowerState = node.powerState
+ val server = when (node.powerState to powerState) {
+ PowerState.POWER_OFF to PowerState.POWER_OFF -> null
+ PowerState.POWER_OFF to PowerState.POWER_ON -> Server(node.uid, node.name, flavor, node.image, ServerState.BUILD)
+ PowerState.POWER_ON to PowerState.POWER_OFF -> null // TODO Terminate existing image
+ PowerState.POWER_ON to PowerState.POWER_ON -> node.server
+ else -> throw IllegalStateException()
+ }
+ node = node.copy(powerState = powerState, server = server)
+
+ if (powerState != previousPowerState && server != null) {
+ launch()
+ }
+
+ return node
+ }
+
+ override suspend fun setImage(image: Image): Node {
+ node = node.copy(image = image)
+ return node
+ }
+
+ override suspend fun refresh(): Node = node
+
+ /**
+ * Launch the server image on the machine.
+ */
+ private suspend fun launch() {
+ val serverCtx = this.serverCtx.serialize()
+
+ processContext.spawn {
+ serverCtx.init()
+ try {
+ node.server!!.image(serverCtx)
+ serverCtx.exit()
+ } catch (cause: Throwable) {
+ serverCtx.exit(cause)
+ }
+ }
+ }
+
+ private val serverCtx = object : ServerManagementContext {
+ override var server: Server
+ get() = node.server!!
+ set(value) {
+ node = node.copy(server = value)
+ }
+
+ override suspend fun init() {
+ val previousState = server.state
+ server = server.copy(state = ServerState.ACTIVE)
+ monitor.onUpdate(server, previousState)
+ }
+
+ override suspend fun exit(cause: Throwable?) {
+ val previousState = server.state
+ val state = if (cause == null) ServerState.SHUTOFF else ServerState.ERROR
+ server = server.copy(state = state)
+ monitor.onUpdate(server, previousState)
+ }
+
+ override suspend fun run(req: LongArray) {
+ // TODO Properly implement this for multiple CPUs
+ val time = max(0, req.max() ?: 0) * flavor.cpus[0].clockRate
+ delay(time.toLong())
+ }
+ }
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/Protocol.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/Protocol.kt
new file mode 100644
index 00000000..a8996f61
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/Protocol.kt
@@ -0,0 +1,146 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal.driver
+
+import com.atlarge.odcsim.ReceivePort
+import com.atlarge.odcsim.SendPort
+import com.atlarge.odcsim.processContext
+import com.atlarge.opendc.compute.core.image.Image
+import com.atlarge.opendc.compute.core.monitor.ServerMonitor
+import com.atlarge.opendc.compute.metal.Node
+import com.atlarge.opendc.compute.metal.PowerState
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+
+/**
+ * Messages that may be sent to the management interface of a bare-metal compute [Node], similar to the
+ * [BareMetalDriver] interface.
+ */
+public sealed class NodeRequest {
+ /**
+ * Initialize the compute node.
+ */
+ public data class Initialize(public val monitor: ServerMonitor) : NodeRequest()
+
+ /**
+ * Update the power state of the compute node.
+ */
+ public data class SetPowerState(public val state: PowerState) : NodeRequest()
+
+ /**
+ * Update the boot disk image of the compute node.
+ */
+ public data class SetImage(public val image: Image) : NodeRequest()
+
+ /**
+ * Obtain the state of the compute node.
+ */
+ public object Refresh : NodeRequest()
+}
+
+/**
+ * Responses emitted by a bare-metal compute [Node].
+ */
+public sealed class NodeResponse {
+ /**
+ * The node that sent this response.
+ */
+ public abstract val node: Node
+
+ /**
+ * A response sent when the bare metal driver has been initialized.
+ */
+ public data class Initialized(public override val node: Node) : NodeResponse()
+
+ /**
+ * A response sent to indicate the power state of the node changed.
+ */
+ public data class PowerStateChanged(public override val node: Node) : NodeResponse()
+
+ /**
+ * A response sent to indicate the image of a node was changed.
+ */
+ public data class ImageChanged(public override val node: Node) : NodeResponse()
+
+ /**
+ * A response sent for obtaining the refreshed [Node] instance.
+ */
+ public data class Refreshed(public override val node: Node) : NodeResponse()
+}
+
+/**
+ * Serialize the specified [BareMetalDriver] instance in order to safely send this object across logical processes.
+ */
+public suspend fun BareMetalDriver.serialize(): BareMetalDriver {
+ val ctx = processContext
+ val input = ctx.open<NodeRequest>()
+ val output = ctx.open<NodeResponse>()
+
+ ctx.launch {
+ val outlet = processContext.connect(output.send)
+ val inlet = processContext.listen(input.receive)
+
+ while (isActive) {
+ when (val msg = inlet.receive()) {
+ is NodeRequest.Initialize ->
+ outlet.send(NodeResponse.Initialized(init(msg.monitor)))
+ is NodeRequest.SetPowerState ->
+ outlet.send(NodeResponse.PowerStateChanged(setPower(msg.state)))
+ is NodeRequest.SetImage ->
+ outlet.send(NodeResponse.ImageChanged(setImage(msg.image)))
+ is NodeRequest.Refresh ->
+ outlet.send(NodeResponse.Refreshed(refresh()))
+ }
+ }
+ }
+
+ return object : BareMetalDriver {
+ private lateinit var inlet: ReceivePort<NodeResponse>
+ private lateinit var outlet: SendPort<NodeRequest>
+
+ override suspend fun init(monitor: ServerMonitor): Node {
+ outlet = processContext.connect(input.send)
+ inlet = processContext.listen(output.receive)
+
+ outlet.send(NodeRequest.Initialize(monitor))
+ return (inlet.receive() as NodeResponse.Initialized).node
+ }
+
+ override suspend fun setPower(powerState: PowerState): Node {
+ outlet.send(NodeRequest.SetPowerState(powerState))
+ return (inlet.receive() as NodeResponse.PowerStateChanged).node
+ }
+
+ override suspend fun setImage(image: Image): Node {
+ outlet.send(NodeRequest.SetImage(image))
+ return (inlet.receive() as NodeResponse.ImageChanged).node
+ }
+
+ override suspend fun refresh(): Node {
+ outlet.send(NodeRequest.Refresh)
+ return (inlet.receive() as NodeResponse.Refreshed).node
+ }
+ }
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/Allocation.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/Allocation.kt
new file mode 100644
index 00000000..3f9ca71b
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/Allocation.kt
@@ -0,0 +1,37 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal.service
+
+import com.atlarge.opendc.compute.metal.Node
+
+/**
+ * Represents an allocation of bare-metal compute nodes.
+ */
+public interface Allocation {
+ /**
+ * The compute nodes that have been allocated.
+ */
+ public val nodes: List<Node>
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt
new file mode 100644
index 00000000..df96f47f
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt
@@ -0,0 +1,55 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal.service
+
+import com.atlarge.opendc.compute.core.image.Image
+import com.atlarge.opendc.compute.core.monitor.ServerMonitor
+import com.atlarge.opendc.compute.metal.Node
+import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
+
+/**
+ * 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
+
+ /**
+ * Allocate the given number of nodes from the provisioner.
+ */
+ public suspend fun allocate(num: Int): Allocation
+
+ /**
+ * 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, allocation: Allocation, image: Image, monitor: ServerMonitor): Node
+}
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt
new file mode 100644
index 00000000..52aa6488
--- /dev/null
+++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt
@@ -0,0 +1,40 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.virt.driver
+
+import com.atlarge.opendc.compute.core.Server
+import com.atlarge.opendc.compute.core.image.Image
+import com.atlarge.opendc.compute.core.monitor.ServerMonitor
+
+/**
+ * A driver interface for a hypervisor running on some host server and communicating with the central compute service to
+ * provide virtualization for that particular resource.
+ */
+public interface VirtDriver {
+ /**
+ * Spawn the given [Image] on the compute resource of this driver.
+ */
+ public suspend fun spawn(image: Image, monitor: ServerMonitor): Server
+}
diff --git a/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriverTest.kt b/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriverTest.kt
new file mode 100644
index 00000000..bc8f677e
--- /dev/null
+++ b/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/FakeBareMetalDriverTest.kt
@@ -0,0 +1,70 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 atlarge-research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.atlarge.opendc.compute.metal.driver
+
+import com.atlarge.odcsim.SimulationEngineProvider
+import com.atlarge.opendc.compute.core.Flavor
+import com.atlarge.opendc.compute.core.ProcessingUnit
+import com.atlarge.opendc.compute.core.Server
+import com.atlarge.opendc.compute.core.ServerState
+import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
+import com.atlarge.opendc.compute.core.monitor.ServerMonitor
+import com.atlarge.opendc.compute.metal.PowerState
+import java.util.ServiceLoader
+import java.util.UUID
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.jupiter.api.Test
+
+internal class FakeBareMetalDriverTest {
+ /**
+ * A smoke test for the bare-metal driver.
+ */
+ @Test
+ fun smoke() {
+ val provider = ServiceLoader.load(SimulationEngineProvider::class.java).first()
+ val system = provider({ ctx ->
+ val flavor = Flavor(listOf(ProcessingUnit("Intel", "Xeon", "amd64", 2300.0, 4)))
+ val image = FlopsApplicationImage(1000, 2)
+ val monitor = object : ServerMonitor {
+ override suspend fun onUpdate(server: Server, previousState: ServerState) {
+ println(server)
+ }
+ }
+ val driver = FakeBareMetalDriver(UUID.randomUUID(), "test", flavor)
+
+ driver.init(monitor)
+ driver.setImage(image)
+ driver.setPower(PowerState.POWER_ON)
+ delay(5)
+ println(driver.refresh())
+ }, name = "sim")
+
+ runBlocking {
+ system.run()
+ system.terminate()
+ }
+ }
+}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 3f10026a..b591c654 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -26,6 +26,7 @@ rootProject.name = "opendc-simulator"
include(":odcsim:odcsim-api")
include(":odcsim:odcsim-engine-omega")
include(":opendc:opendc-core")
+include(":opendc:opendc-compute")
include(":opendc:opendc-format")
include(":opendc:opendc-workflows")
include(":opendc:opendc-experiments-tpds")