diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2020-02-14 00:53:24 +0100 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2020-02-14 00:53:24 +0100 |
| commit | 3fc32c0b6f02d245a544aaaa061094231830f661 (patch) | |
| tree | cf55b824a1d6746f7d218c39f0db1cc53a662edb | |
| parent | d40eae0264236be3a9d34f39a63adde8a9b47a57 (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.
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") |
