summaryrefslogtreecommitdiff
path: root/simulator/opendc/opendc-compute
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2020-10-01 00:49:53 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2020-10-01 10:19:13 +0200
commit8a9f5573bef3f68316add17c04a47cc4e5fe75fa (patch)
tree8dff00c904d5db65e9baf0e7ca2d18a8a61800c1 /simulator/opendc/opendc-compute
parent27ddd462d148d70760e45f967387905054e21d20 (diff)
Move OpenDC modules into simulator root
This change moves the OpenDC modules previously living in the simulator/opendc directory to the simulator directory itself given that we do not make a distinction between OpenDC and odcsim anymore.
Diffstat (limited to 'simulator/opendc/opendc-compute')
-rw-r--r--simulator/opendc/opendc-compute/build.gradle.kts42
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt41
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/MemoryUnit.kt40
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingNode.kt40
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt38
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt80
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerEvent.kt53
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt55
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt169
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt40
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt53
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt40
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt67
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt3
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt46
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt32
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt123
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt25
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Metadata.kt34
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt74
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeEvent.kt43
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeState.kt55
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt88
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt475
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/power/PowerModels.kt45
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt66
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningService.kt67
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/Hypervisor.kt58
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorEvent.kt78
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt57
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/InsufficientMemoryOnServerException.kt3
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/SimpleVirtDriver.kt634
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt56
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt15
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt358
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningEvent.kt49
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt42
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt25
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableCoreMemoryAllocationPolicy.kt40
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt15
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ComparableAllocationPolicyLogic.kt52
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt15
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ProvisionedCoresAllocationPolicy.kt42
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/RandomAllocationPolicy.kt51
-rw-r--r--simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt34
-rw-r--r--simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImageTest.kt78
-rw-r--r--simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt83
-rw-r--r--simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt70
-rw-r--r--simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt169
49 files changed, 0 insertions, 3958 deletions
diff --git a/simulator/opendc/opendc-compute/build.gradle.kts b/simulator/opendc/opendc-compute/build.gradle.kts
deleted file mode 100644
index e65615e8..00000000
--- a/simulator/opendc/opendc-compute/build.gradle.kts
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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 {
- api(project(":opendc:opendc-core"))
- implementation(project(":opendc:opendc-utils"))
- implementation("io.github.microutils:kotlin-logging:1.7.9")
-
- testImplementation(project(":opendc:opendc-simulator"))
- testRuntimeOnly("org.slf4j:slf4j-simple:${Library.SLF4J}")
- testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
- testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
- testImplementation("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}")
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt
deleted file mode 100644
index a49d3abf..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Flavor.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core
-
-/**
- * Flavors define the compute and memory capacity of [Server] instance. To put it simply, a flavor is an available
- * hardware configuration for a server. It defines the size of a virtual server that can be launched.
- */
-public data class Flavor(
- /**
- * The number of (virtual) processing cores to use.
- */
- public val cpuCount: Int,
-
- /**
- * The amount of RAM available to the server (in MB).
- */
- public val memorySize: Long
-)
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/MemoryUnit.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/MemoryUnit.kt
deleted file mode 100644
index ce57fc72..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/MemoryUnit.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core
-
-/**
- * A memory unit of a compute resource, either virtual or physical.
- *
- * @property vendor The vendor string of the memory.
- * @property modelName The name of the memory model.
- * @property speed The access speed of the memory in MHz.
- * @property size The size of the memory unit in MBs.
- */
-public data class MemoryUnit(
- public val vendor: String,
- public val modelName: String,
- public val speed: Double,
- public val size: Long
-)
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingNode.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingNode.kt
deleted file mode 100644
index 91f5dde9..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingNode.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core
-
-/**
- * A processing node/package/socket containing possibly several CPU cores.
- *
- * @property vendor The vendor string of the processor node.
- * @property modelName The name of the processor node.
- * @property arch The micro-architecture of the processor node.
- * @property coreCount The number of logical CPUs in the processor node.
- */
-data class ProcessingNode(
- val vendor: String,
- val arch: String,
- val modelName: String,
- val coreCount: Int
-)
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt
deleted file mode 100644
index ba148ee0..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ProcessingUnit.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core
-
-/**
- * A single logical compute unit of processor node, either virtual or physical.
- *
- * @property node The processing node containing the CPU core.
- * @property id The identifier of the CPU core within the processing node.
- * @property frequency The clock rate of the CPU in MHz.
- */
-public data class ProcessingUnit(
- public val node: ProcessingNode,
- public val id: Int,
- public val frequency: Double
-)
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt
deleted file mode 100644
index 01968cd8..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/Server.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core
-
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.core.resource.Resource
-import com.atlarge.opendc.core.resource.TagContainer
-import com.atlarge.opendc.core.services.ServiceRegistry
-import kotlinx.coroutines.flow.Flow
-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 tags of this server.
- */
- public override val tags: TagContainer,
-
- /**
- * 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,
-
- /**
- * The services published by this server.
- */
- public val services: ServiceRegistry,
-
- /**
- * The events that are emitted by the server.
- */
- public val events: Flow<ServerEvent>
-) : Resource {
- override fun hashCode(): Int = uid.hashCode()
- override fun equals(other: Any?): Boolean = other is Server && uid == other.uid
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerEvent.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerEvent.kt
deleted file mode 100644
index 1595937c..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerEvent.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core
-
-import com.atlarge.opendc.core.services.ServiceKey
-
-/**
- * An event that is emitted by a [Server].
- */
-public sealed class ServerEvent {
- /**
- * The server that emitted the event.
- */
- public abstract val server: Server
-
- /**
- * This event is emitted when the state of [server] changes.
- *
- * @property server The server of which the state changed.
- * @property previousState The previous state of the server.
- */
- public data class StateChanged(override val server: Server, val previousState: ServerState) : ServerEvent()
-
- /**
- * This event is emitted when a server publishes a service.
- *
- * @property server The server that published the service.
- * @property key The service key of the service that was published.
- */
- public data class ServicePublished(override val server: Server, val key: ServiceKey<*>) : ServerEvent()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt
deleted file mode 100644
index 27372a5e..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/ServerState.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package 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/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt
deleted file mode 100644
index 817bee4b..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerContext.kt
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.execution
-
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.core.services.ServiceKey
-import kotlinx.coroutines.selects.SelectClause0
-import kotlinx.coroutines.selects.select
-import java.time.Clock
-
-/**
- * Represents the execution context in which a bootable [Image] runs on a [Server].
- */
-public interface ServerContext {
- /**
- * The virtual clock.
- */
- public val clock: Clock
-
- /**
- * The server on which the image runs.
- */
- public val server: Server
-
- /**
- * A list of processing units available to use.
- */
- public val cpus: List<ProcessingUnit>
-
- /**
- * Publish the specified [service] at the given [ServiceKey].
- */
- public suspend fun <T : Any> publishService(key: ServiceKey<T>, service: T)
-
- /**
- * Ask the processor cores to run the specified [slice] and suspend execution until the trigger condition is met as
- * specified by [triggerMode].
- *
- * After the method returns, [Slice.burst] will contain the remaining burst length for each of the cores (which
- * may be zero). These changes may happen anytime during execution of this method and callers should not rely on
- * the timing of this change.
- *
- * @param slice The representation of work to run on the processors.
- * @param triggerMode The trigger condition to resume execution.
- */
- public suspend fun run(slice: Slice, triggerMode: TriggerMode = TriggerMode.FIRST) =
- select<Unit> { onRun(slice, triggerMode).invoke {} }
-
- /**
- * Ask the processors cores to run the specified [batch] of work slices and suspend execution until the trigger
- * condition is met as specified by [triggerMode].
- *
- * After the method returns, [Slice.burst] will contain the remaining burst length for each of the cores (which
- * may be zero). These changes may happen anytime during execution of this method and callers should not rely on
- * the timing of this change.
- *
- * In case slices in the batch do not finish processing before their deadline, [merge] is called to merge these
- * slices with the next slice to be executed.
- *
- * @param batch The batch of work to run on the processors.
- * @param triggerMode The trigger condition to resume execution.
- * @param merge The merge function for consecutive slices in case the last slice was not completed within its
- * deadline.
- */
- public suspend fun run(
- batch: Sequence<Slice>,
- triggerMode: TriggerMode = TriggerMode.FIRST,
- merge: (Slice, Slice) -> Slice = { _, r -> r }
- ) = select<Unit> { onRun(batch, triggerMode, merge).invoke {} }
-
- /**
- * Ask the processor cores to run the specified [slice] and select when the trigger condition is met as specified
- * by [triggerMode].
- *
- * After the method returns, [Slice.burst] will contain the remaining burst length for each of the cores (which
- * may be zero). These changes may happen anytime during execution of this method and callers should not rely on
- * the timing of this change.
- *
- * @param slice The representation of work to request from the processors.
- * @param triggerMode The trigger condition to resume execution.
- */
- public fun onRun(slice: Slice, triggerMode: TriggerMode = TriggerMode.FIRST): SelectClause0 =
- onRun(sequenceOf(slice), triggerMode)
-
- /**
- * Ask the processors cores to run the specified [batch] of work slices and select when the trigger condition is met
- * as specified by [triggerMode].
- *
- * After the method returns, [Slice.burst] will contain the remaining burst length for each of the cores (which
- * may be zero). These changes may happen anytime during execution of this method and callers should not rely on
- * the timing of this change.
- *
- * In case slices in the batch do not finish processing before their deadline, [merge] is called to merge these
- * slices with the next slice to be executed.
- *
- * @param batch The batch of work to run on the processors.
- * @param triggerMode The trigger condition to resume execution during the **last** slice.
- * @param merge The merge function for consecutive slices in case the last slice was not completed within its
- * deadline.
- */
- public fun onRun(
- batch: Sequence<Slice>,
- triggerMode: TriggerMode = TriggerMode.FIRST,
- merge: (Slice, Slice) -> Slice = { _, r -> r }
- ): SelectClause0
-
- /**
- * A request to the host machine for a slice of CPU time from the processor cores.
- *
- * Both [burst] and [limit] must be of the same size and in any other case the method will throw an
- * [IllegalArgumentException].
- *
- *
- * @param burst The burst time to request from each of the processor cores.
- * @param limit The maximum usage in terms of MHz that the processing core may use while running the burst.
- * @param deadline The instant at which this slice needs to be fulfilled.
- */
- public class Slice(val burst: LongArray, val limit: DoubleArray, val deadline: Long) {
- init {
- require(burst.size == limit.size) { "Incompatible array dimensions" }
- }
- }
-
- /**
- * The modes for triggering a machine exit from the machine.
- */
- public enum class TriggerMode {
- /**
- * A machine exit occurs when either the first processor finishes processing a **non-zero** burst or the
- * deadline is reached.
- */
- FIRST,
-
- /**
- * A machine exit occurs when either the last processor finishes processing a **non-zero** burst or the deadline
- * is reached.
- */
- LAST,
-
- /**
- * A machine exit occurs only when the deadline is reached.
- */
- DEADLINE
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt
deleted file mode 100644
index 5a9b725b..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ServerManagementContext.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.execution
-
-/**
- * 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/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt
deleted file mode 100644
index e4da557b..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/execution/ShutdownException.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.execution
-
-import kotlinx.coroutines.CancellationException
-
-/**
- * This exception is thrown by the underlying [ServerContext] to indicate that a shutdown flow
- * has been sent to the server.
- */
-public class ShutdownException(message: String? = null, override val cause: Throwable? = null) : CancellationException(message)
-
-/**
- * This method terminates the current active coroutine if the specified [CancellationException] is caused
- * by a shutdown.
- */
-public fun CancellationException.assertShutdown() {
- if (this is ShutdownException) {
- throw this
- }
-}
-
-/**
- * This method terminates the current active coroutine if the specified [CancellationException] is caused
- * by a failure.
- */
-public fun CancellationException.assertFailure() {
- if (this is ShutdownException && cause != null) {
- throw this
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt
deleted file mode 100644
index 8f6c4682..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/EmptyImage.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.image
-
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.TagContainer
-import java.util.UUID
-
-/**
- * An empty boot disk [Image] that exits immediately on start.
- */
-object EmptyImage : Image {
- override val uid: UUID = UUID.randomUUID()
- override val name: String = "empty"
- override val tags: TagContainer = emptyMap()
-
- override suspend fun invoke(ctx: ServerContext) {}
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt
deleted file mode 100644
index d65e7e94..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImage.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.image
-
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.TagContainer
-import java.util.UUID
-import kotlin.math.min
-
-/**
- * An application [Image] that models applications performing a static number of floating point operations ([flops]) on
- * a compute resource.
- *
- * @property uid The unique identifier of this image.
- * @property name The name of this image.
- * @property tags The tags attached to the image.
- * @property flops The number of floating point operations to perform for this task in MFLOPs.
- * @property cores The number of cores that the image is able to utilize.
- * @property utilization A model of the CPU utilization of the application.
- */
-data class FlopsApplicationImage(
- public override val uid: UUID,
- public override val name: String,
- public override val tags: TagContainer,
- public val flops: Long,
- public val cores: Int,
- public val utilization: Double = 0.8
-) : Image {
- init {
- require(flops >= 0) { "Negative number of flops" }
- require(cores > 0) { "Negative number of cores or no cores" }
- require(utilization > 0.0 && utilization <= 1.0) { "Utilization must be in (0, 1]" }
- }
-
- /**
- * Execute the runtime behavior based on a number of floating point operations to execute.
- */
- override suspend fun invoke(ctx: ServerContext) {
- val cores = min(this.cores, ctx.server.flavor.cpuCount)
- val burst = LongArray(cores) { flops / cores }
- val maxUsage = DoubleArray(cores) { i -> ctx.cpus[i].frequency * utilization }
-
- ctx.run(ServerContext.Slice(burst, maxUsage, Long.MAX_VALUE), triggerMode = ServerContext.TriggerMode.LAST)
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt
deleted file mode 100644
index 5b0035e3..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.atlarge.opendc.compute.core.image
-
-data class FlopsHistoryFragment(val tick: Long, val flops: Long, val duration: Long, val usage: Double, val cores: Int)
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt
deleted file mode 100644
index 52d4d7b5..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/Image.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.image
-
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.Resource
-
-/**
- * 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 : Resource {
- /**
- * Launch the machine image in the specified [ServerContext].
- *
- * This method should encapsulate and characterize the runtime behavior of the instance resulting from launching
- * the image on some machine, in terms of the resource consumption on the machine.
- */
- public suspend operator fun invoke(ctx: ServerContext)
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt
deleted file mode 100644
index 0e1af093..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.atlarge.opendc.compute.core.image
-
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.core.resource.TagContainer
-import java.util.UUID
-import kotlin.math.min
-
-class VmImage(
- public override val uid: UUID,
- public override val name: String,
- public override val tags: TagContainer,
- public val flopsHistory: Sequence<FlopsHistoryFragment>,
- public val maxCores: Int,
- public val requiredMemory: Long
-) : Image {
-
- override suspend fun invoke(ctx: ServerContext) {
- var offset = ctx.clock.millis()
-
- val batch = flopsHistory.map { fragment ->
- val cores = min(fragment.cores, ctx.server.flavor.cpuCount)
- val burst = LongArray(cores) { fragment.flops / cores }
- val usage = DoubleArray(cores) { fragment.usage / cores }
- offset += fragment.duration
- ServerContext.Slice(burst, usage, offset)
- }
-
- ctx.run(batch)
- }
-
- override fun toString(): String = "VmImage(uid=$uid, name=$name, cores=$maxCores, requiredMemory=$requiredMemory)"
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt
deleted file mode 100644
index 3f885f89..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/PerformanceInterferenceModel.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.workload
-
-import com.atlarge.opendc.compute.core.Server
-import java.util.*
-import kotlin.random.Random
-
-/**
- * Meta-data key for the [PerformanceInterferenceModel] of an image.
- */
-const val IMAGE_PERF_INTERFERENCE_MODEL = "image:performance-interference"
-
-/**
- * Performance Interference Model describing the variability incurred by different sets of workloads if colocated.
- *
- * @param items The [PerformanceInterferenceModelItem]s that make up this model.
- */
-class PerformanceInterferenceModel(
- val items: SortedSet<PerformanceInterferenceModelItem>,
- val random: Random = Random(0)
-) {
- private var intersectingItems: List<PerformanceInterferenceModelItem> = emptyList()
- private val colocatedWorkloads = TreeMap<String, Int>()
-
- fun vmStarted(server: Server) {
- colocatedWorkloads.merge(server.image.name, 1, Int::plus)
- intersectingItems = items.filter { item -> doesMatch(item) }
- }
-
- fun vmStopped(server: Server) {
- colocatedWorkloads.computeIfPresent(server.image.name) { _, v -> (v - 1).takeUnless { it == 0 } }
- intersectingItems = items.filter { item -> doesMatch(item) }
- }
-
- private fun doesMatch(item: PerformanceInterferenceModelItem): Boolean {
- var count = 0
- for (name in item.workloadNames.subSet(colocatedWorkloads.firstKey(), colocatedWorkloads.lastKey() + "\u0000")) {
- count += colocatedWorkloads.getOrDefault(name, 0)
- if (count > 1)
- return true
- }
- return false
- }
-
- fun apply(currentServerLoad: Double): Double {
- if (intersectingItems.isEmpty()) {
- return 1.0
- }
- val score = intersectingItems
- .firstOrNull { it.minServerLoad <= currentServerLoad }
-
- // Apply performance penalty to (on average) only one of the VMs
- return if (score != null && random.nextInt(score.workloadNames.size) == 0) {
- score.performanceScore
- } else {
- 1.0
- }
- }
-}
-
-/**
- * Model describing how a specific set of workloads causes performance variability for each workload.
- *
- * @param workloadNames The names of the workloads that together cause performance variability for each workload in the set.
- * @param minServerLoad The minimum total server load at which this interference is activated and noticeable.
- * @param performanceScore The performance score that should be applied to each workload's performance. 1 means no
- * influence, <1 means that performance degrades, and >1 means that performance improves.
- */
-data class PerformanceInterferenceModelItem(
- val workloadNames: SortedSet<String>,
- val minServerLoad: Double,
- val performanceScore: Double
-) : Comparable<PerformanceInterferenceModelItem> {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as PerformanceInterferenceModelItem
-
- if (workloadNames != other.workloadNames) return false
-
- return true
- }
-
- override fun hashCode(): Int = workloadNames.hashCode()
-
- override fun compareTo(other: PerformanceInterferenceModelItem): Int {
- var cmp = performanceScore.compareTo(other.performanceScore)
- if (cmp != 0) {
- return cmp
- }
-
- cmp = minServerLoad.compareTo(other.minServerLoad)
- if (cmp != 0) {
- return cmp
- }
-
- return hashCode().compareTo(other.hashCode())
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt
deleted file mode 100644
index 098eb8ca..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/workload/VmWorkload.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.atlarge.opendc.compute.core.workload
-
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.core.User
-import com.atlarge.opendc.core.workload.Workload
-import java.util.UUID
-
-/**
- * A workload that represents a VM.
- *
- * @property uid A unique identified of this VM.
- * @property name The name of this VM.
- * @property owner The owner of the VM.
- * @property image The image of the VM.
- */
-data class VmWorkload(
- override val uid: UUID,
- override val name: String,
- override val owner: User,
- val image: VmImage
-) : Workload {
- override fun equals(other: Any?): Boolean = other is VmWorkload && uid == other.uid
-
- override fun hashCode(): Int = uid.hashCode()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Metadata.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Metadata.kt
deleted file mode 100644
index a3a851fe..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Metadata.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal
-
-/*
- * Common metadata keys for bare-metal nodes.
- */
-
-/**
- * The cluster to which the node belongs.
- */
-const val NODE_CLUSTER = "bare-metal:cluster"
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt
deleted file mode 100644
index 7cb4c0c5..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/Node.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal
-
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.core.Identity
-import kotlinx.coroutines.flow.Flow
-import java.util.UUID
-
-/**
- * A bare-metal compute node.
- */
-public data class Node(
- /**
- * The unique identifier of the node.
- */
- public override val uid: UUID,
-
- /**
- * The optional name of the node.
- */
- public override val name: String,
-
- /**
- * Metadata of the node.
- */
- public val metadata: Map<String, Any>,
-
- /**
- * The last known state of the compute node.
- */
- public val state: NodeState,
-
- /**
- * The 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?,
-
- /**
- * The events that are emitted by the node.
- */
- public val events: Flow<NodeEvent>
-) : Identity {
- override fun hashCode(): Int = uid.hashCode()
- override fun equals(other: Any?): Boolean = other is Node && uid == other.uid
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeEvent.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeEvent.kt
deleted file mode 100644
index 7719db24..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeEvent.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal
-
-/**
- * An event that is emitted by a [Node].
- */
-public sealed class NodeEvent {
- /**
- * The node that emitted the event.
- */
- public abstract val node: Node
-
- /**
- * This event is emitted when the state of [node] changes.
- *
- * @property node The node of which the state changed.
- * @property previousState The previous state of the node.
- */
- public data class StateChanged(override val node: Node, val previousState: NodeState) : NodeEvent()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeState.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeState.kt
deleted file mode 100644
index ca9cf509..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/NodeState.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal
-
-/**
- * An enumeration describing the possible states of a bare-metal compute node.
- */
-public enum class NodeState {
- /**
- * The node is booting.
- */
- BOOT,
-
- /**
- * The node is powered off.
- */
- SHUTOFF,
-
- /**
- * The node is active and running.
- */
- ACTIVE,
-
- /**
- * The node is in error.
- */
- ERROR,
-
- /**
- * The state of the node is unknown.
- */
- UNKNOWN,
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt
deleted file mode 100644
index 41cec291..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/BareMetalDriver.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.driver
-
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.core.failure.FailureDomain
-import com.atlarge.opendc.core.power.Powerable
-import com.atlarge.opendc.core.services.AbstractServiceKey
-import kotlinx.coroutines.flow.Flow
-import java.util.UUID
-
-/**
- * A driver interface for the management interface of a bare-metal compute node.
- */
-public interface BareMetalDriver : Powerable, FailureDomain {
- /**
- * The [Node] that is controlled by this driver.
- */
- public val node: Flow<Node>
-
- /**
- * The amount of work done by the machine in percentage with respect to the total amount of processing power
- * available.
- */
- public val usage: Flow<Double>
-
- /**
- * Initialize the driver.
- */
- public suspend fun init(): Node
-
- /**
- * Start the bare metal node with the specified boot disk image.
- */
- public suspend fun start(): Node
-
- /**
- * Stop the bare metal node if it is running.
- */
- public suspend fun stop(): Node
-
- /**
- * Reboot the bare metal node.
- */
- public suspend fun reboot(): Node
-
- /**
- * Update the boot disk image of the compute node.
- *
- * Changing the boot disk image of node does not affect it while the node is running. In order to start the new boot
- * disk image, the compute node must be restarted.
- */
- public suspend fun setImage(image: Image): Node
-
- /**
- * Obtain the state of the compute node.
- */
- public suspend fun refresh(): Node
-
- /**
- * A key that allows access to the [BareMetalDriver] instance from a [Server] that runs on the bare-metal machine.
- */
- companion object Key : AbstractServiceKey<BareMetalDriver>(UUID.randomUUID(), "bare-metal:driver")
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt
deleted file mode 100644
index 0c758e6b..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.driver
-
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.MemoryUnit
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.compute.core.execution.ServerManagementContext
-import com.atlarge.opendc.compute.core.execution.ShutdownException
-import com.atlarge.opendc.compute.core.image.EmptyImage
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.metal.NodeEvent
-import com.atlarge.opendc.compute.metal.NodeState
-import com.atlarge.opendc.compute.metal.power.ConstantPowerModel
-import com.atlarge.opendc.core.power.PowerModel
-import com.atlarge.opendc.core.services.ServiceKey
-import com.atlarge.opendc.core.services.ServiceRegistry
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Delay
-import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.FlowPreview
-import kotlinx.coroutines.InternalCoroutinesApi
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.intrinsics.startCoroutineCancellable
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.selects.SelectClause0
-import kotlinx.coroutines.selects.SelectInstance
-import org.opendc.utils.flow.EventFlow
-import org.opendc.utils.flow.StateFlow
-import java.lang.Exception
-import java.time.Clock
-import java.util.UUID
-import kotlin.coroutines.ContinuationInterceptor
-import kotlin.math.ceil
-import kotlin.math.max
-import kotlin.math.min
-import kotlin.random.Random
-
-/**
- * A basic implementation of the [BareMetalDriver] that simulates an [Image] running on a bare-metal machine.
- *
- * @param coroutineScope The [CoroutineScope] the driver runs in.
- * @param clock The virtual clock to keep track of time.
- * @param uid The unique identifier of the machine.
- * @param name An optional name of the machine.
- * @param metadata The initial metadata of the node.
- * @param cpus The CPUs available to the bare metal machine.
- * @param memoryUnits The memory units in this machine.
- * @param powerModel The power model of this machine.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-public class SimpleBareMetalDriver(
- private val coroutineScope: CoroutineScope,
- private val clock: Clock,
- uid: UUID,
- name: String,
- metadata: Map<String, Any>,
- val cpus: List<ProcessingUnit>,
- val memoryUnits: List<MemoryUnit>,
- powerModel: PowerModel<SimpleBareMetalDriver> = ConstantPowerModel(
- 0.0
- )
-) : BareMetalDriver {
- /**
- * The flavor that corresponds to this machine.
- */
- private val flavor = Flavor(cpus.size, memoryUnits.map { it.size }.sum())
-
- /**
- * The current active server context.
- */
- private var serverContext: BareMetalServerContext? = null
-
- /**
- * The events of the machine.
- */
- private val events = EventFlow<NodeEvent>()
-
- /**
- * The flow containing the load of the server.
- */
- private val usageState = MutableStateFlow(0.0)
-
- /**
- * The machine state.
- */
- private val nodeState = StateFlow(Node(uid, name, metadata + ("driver" to this), NodeState.SHUTOFF, EmptyImage, null, events))
-
- override val node: Flow<Node> = nodeState
-
- @OptIn(FlowPreview::class)
- override val usage: Flow<Double> = usageState
-
- override val powerDraw: Flow<Double> = powerModel(this)
-
- /**
- * The internal random instance.
- */
- private val random = Random(uid.leastSignificantBits xor uid.mostSignificantBits)
-
- override suspend fun init(): Node {
- return nodeState.value
- }
-
- override suspend fun start(): Node {
- val node = nodeState.value
- if (node.state != NodeState.SHUTOFF) {
- return node
- }
-
- val events = EventFlow<ServerEvent>()
- val server = Server(
- UUID(random.nextLong(), random.nextLong()),
- node.name,
- emptyMap(),
- flavor,
- node.image,
- ServerState.BUILD,
- ServiceRegistry().put(BareMetalDriver, this@SimpleBareMetalDriver),
- events
- )
-
- setNode(node.copy(state = NodeState.BOOT, server = server))
- serverContext = BareMetalServerContext(events)
- return nodeState.value
- }
-
- override suspend fun stop(): Node {
- val node = nodeState.value
- if (node.state == NodeState.SHUTOFF) {
- return node
- }
-
- // We terminate the image running on the machine
- serverContext!!.cancel(fail = false)
- serverContext = null
-
- setNode(node.copy(state = NodeState.SHUTOFF, server = null))
- return node
- }
-
- override suspend fun reboot(): Node {
- stop()
- return start()
- }
-
- override suspend fun setImage(image: Image): Node {
- setNode(nodeState.value.copy(image = image))
- return nodeState.value
- }
-
- override suspend fun refresh(): Node = nodeState.value
-
- private fun setNode(value: Node) {
- val field = nodeState.value
- if (field.state != value.state) {
- events.emit(NodeEvent.StateChanged(value, field.state))
- }
-
- if (field.server != null && value.server != null && field.server.state != value.server.state) {
- serverContext!!.events.emit(ServerEvent.StateChanged(value.server, field.server.state))
- }
-
- nodeState.value = value
- }
-
- private inner class BareMetalServerContext(val events: EventFlow<ServerEvent>) : ServerManagementContext {
- private var finalized: Boolean = false
-
- // A state in which the machine is still available, but does not run any of the work requested by the
- // image
- var unavailable = false
-
- override val cpus: List<ProcessingUnit> = this@SimpleBareMetalDriver.cpus
-
- override val server: Server
- get() = nodeState.value.server!!
-
- override val clock: Clock
- get() = this@SimpleBareMetalDriver.clock
-
- private val job = coroutineScope.launch {
- delay(1) // TODO Introduce boot time
- init()
- try {
- server.image(this@BareMetalServerContext)
- exit()
- } catch (cause: Throwable) {
- exit(cause)
- }
- }
-
- /**
- * Cancel the image running on the machine.
- */
- suspend fun cancel(fail: Boolean) {
- if (fail)
- job.cancel(ShutdownException(cause = Exception("Random failure")))
- else
- job.cancel(ShutdownException())
- job.join()
- }
-
- override suspend fun <T : Any> publishService(key: ServiceKey<T>, service: T) {
- val server = server.copy(services = server.services.put(key, service))
- setNode(nodeState.value.copy(server = server))
- events.emit(ServerEvent.ServicePublished(server, key))
- }
-
- override suspend fun init() {
- assert(!finalized) { "Machine is already finalized" }
-
- val server = server.copy(state = ServerState.ACTIVE)
- setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
- }
-
- override suspend fun exit(cause: Throwable?) {
- finalized = true
-
- val newServerState =
- if (cause == null || (cause is ShutdownException && cause.cause == null))
- ServerState.SHUTOFF
- else
- ServerState.ERROR
- val newNodeState =
- if (cause == null || (cause is ShutdownException && cause.cause != null))
- nodeState.value.state
- else
- NodeState.ERROR
- val server = server.copy(state = newServerState)
- setNode(nodeState.value.copy(state = newNodeState, server = server))
- }
-
- /**
- * A disposable to prevent resetting the usage state for subsequent calls to onRun.
- */
- private var usageFlush: DisposableHandle? = null
-
- /**
- * Cache the [Delay] instance for timing.
- *
- * XXX We need to cache this before the call to [onRun] since doing this in [onRun] is too heavy.
- * XXX Note however that this is an ugly hack which may break in the future.
- */
- @OptIn(InternalCoroutinesApi::class)
- private val delay = coroutineScope.coroutineContext[ContinuationInterceptor] as Delay
-
- @OptIn(InternalCoroutinesApi::class)
- override fun onRun(
- batch: Sequence<ServerContext.Slice>,
- triggerMode: ServerContext.TriggerMode,
- merge: (ServerContext.Slice, ServerContext.Slice) -> ServerContext.Slice
- ): SelectClause0 {
- assert(!finalized) { "Server instance is already finalized" }
-
- return object : SelectClause0 {
- @InternalCoroutinesApi
- override fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R) {
- // Do not reset the usage state: we will set it ourselves
- usageFlush?.dispose()
- usageFlush = null
-
- val queue = batch.iterator()
- var start = Long.MIN_VALUE
- var currentWork: SliceWork? = null
- var currentDisposable: DisposableHandle? = null
-
- fun schedule(slice: ServerContext.Slice) {
- start = clock.millis()
-
- val isLastSlice = !queue.hasNext()
- val work = SliceWork(slice)
- val candidateDuration = when (triggerMode) {
- ServerContext.TriggerMode.FIRST -> work.minExit
- ServerContext.TriggerMode.LAST -> work.maxExit
- ServerContext.TriggerMode.DEADLINE -> slice.deadline - start
- }
-
- // Check whether the deadline is exceeded during the run of the slice.
- val duration = min(candidateDuration, slice.deadline - start)
-
- val action = Runnable {
- currentWork = null
-
- // Flush all the work that was performed
- val hasFinished = work.stop(duration)
-
- if (!isLastSlice) {
- val candidateSlice = queue.next()
- val nextSlice =
- // If our previous slice exceeds its deadline, merge it with the next candidate slice
- if (hasFinished)
- candidateSlice
- else
- merge(candidateSlice, slice)
- schedule(nextSlice)
- } else if (select.trySelect()) {
- block.startCoroutineCancellable(select.completion)
- }
- }
-
- // Schedule the flush after the entire slice has finished
- currentDisposable = delay.invokeOnTimeout(duration, action)
-
- // Start the slice work
- currentWork = work
- work.start()
- }
-
- // Schedule the first work
- if (queue.hasNext()) {
- schedule(queue.next())
-
- // A DisposableHandle to flush the work in case the call is cancelled
- val disposable = DisposableHandle {
- val end = clock.millis()
- val duration = end - start
-
- currentWork?.stop(duration)
- currentDisposable?.dispose()
-
- // Schedule reset the usage of the machine since the call is returning
- usageFlush = delay.invokeOnTimeout(1) {
- usageState.value = 0.0
- usageFlush = null
- }
- }
-
- select.disposeOnSelect(disposable)
- } else if (select.trySelect()) {
- // No work has been given: select immediately
- block.startCoroutineCancellable(select.completion)
- }
- }
- }
- }
-
- /**
- * A slice to be processed.
- */
- private inner class SliceWork(val slice: ServerContext.Slice) {
- /**
- * The duration after which the first processor finishes processing this slice.
- */
- public val minExit: Long
-
- /**
- * The duration after which the last processor finishes processing this slice.
- */
- public val maxExit: Long
-
- /**
- * A flag to indicate that the slice will exceed the deadline.
- */
- public val exceedsDeadline: Boolean
- get() = slice.deadline < maxExit
-
- /**
- * The total amount of CPU usage.
- */
- public val totalUsage: Double
-
- /**
- * A flag to indicate that this slice is empty.
- */
- public val isEmpty: Boolean
-
- init {
- var totalUsage = 0.0
- var minExit = Long.MAX_VALUE
- var maxExit = 0L
- var nonEmpty = false
-
- // Determine the duration of the first/last CPU to finish
- for (i in 0 until min(cpus.size, slice.burst.size)) {
- val cpu = cpus[i]
- val usage = min(slice.limit[i], cpu.frequency)
- val cpuDuration = ceil(slice.burst[i] / usage * 1000).toLong() // Convert from seconds to milliseconds
-
- totalUsage += usage / cpu.frequency
-
- if (cpuDuration != 0L) { // We only wait for processor cores with a non-zero burst
- minExit = min(minExit, cpuDuration)
- maxExit = max(maxExit, cpuDuration)
- nonEmpty = true
- }
- }
-
- this.isEmpty = !nonEmpty
- this.totalUsage = totalUsage
- this.minExit = minExit
- this.maxExit = maxExit
- }
-
- /**
- * Indicate that the work on the slice has started.
- */
- public fun start() {
- usageState.value = totalUsage / cpus.size
- }
-
- /**
- * Flush the work performed on the slice.
- */
- public fun stop(duration: Long): Boolean {
- var hasFinished = true
-
- // Only flush the work if the machine is available
- if (!unavailable) {
- for (i in 0 until min(cpus.size, slice.burst.size)) {
- val usage = min(slice.limit[i], cpus[i].frequency)
- val granted = ceil(duration / 1000.0 * usage).toLong()
- val res = max(0, slice.burst[i] - granted)
- slice.burst[i] = res
-
- if (res != 0L) {
- hasFinished = false
- }
- }
- }
-
- return hasFinished
- }
- }
- }
-
- override val scope: CoroutineScope
- get() = coroutineScope
-
- override suspend fun fail() {
- serverContext?.unavailable = true
-
- val server = nodeState.value.server?.copy(state = ServerState.ERROR)
- setNode(nodeState.value.copy(state = NodeState.ERROR, server = server))
- }
-
- override suspend fun recover() {
- serverContext?.unavailable = false
-
- val server = nodeState.value.server?.copy(state = ServerState.ACTIVE)
- setNode(nodeState.value.copy(state = NodeState.ACTIVE, server = server))
- }
-
- override fun toString(): String = "SimpleBareMetalDriver(node = ${nodeState.value.uid})"
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/power/PowerModels.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/power/PowerModels.kt
deleted file mode 100644
index 9ddbe08e..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/power/PowerModels.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.power
-
-import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
-import com.atlarge.opendc.core.power.PowerModel
-import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
-
-/**
- * A power model which emits a single value.
- */
-public fun ConstantPowerModel(value: Double): PowerModel<BareMetalDriver> = { _ -> flowOf(value) }
-
-/**
- * A power model that assumes a naive linear relation between power usage and host CPU utilization.
- *
- * @param idle The power draw in Watts on idle.
- * @param max The maximum power draw in Watts of the server.
- */
-public fun LinearLoadPowerModel(idle: Double, max: Double): PowerModel<BareMetalDriver> = { driver ->
- driver.usage.map { load -> (max - idle) * load + idle }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt
deleted file mode 100644
index a54d8df4..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/ProvisioningService.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.service
-
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
-import com.atlarge.opendc.core.services.AbstractServiceKey
-import java.util.UUID
-
-/**
- * A cloud platform service for provisioning bare-metal compute nodes on the platform.
- */
-public interface ProvisioningService {
- /**
- * Create a new bare-metal compute node.
- */
- public suspend fun create(driver: BareMetalDriver): Node
-
- /**
- * Obtain the available nodes.
- */
- public suspend fun nodes(): Set<Node>
-
- /**
- * Refresh the state of a compute node.
- */
- public suspend fun refresh(node: Node): Node
-
- /**
- * Deploy the specified [Image] on a compute node.
- */
- public suspend fun deploy(node: Node, image: Image): Node
-
- /**
- * Stop the specified [Node] .
- */
- public suspend fun stop(node: Node): Node
-
- /**
- * The service key of this service.
- */
- companion object Key : AbstractServiceKey<ProvisioningService>(UUID.randomUUID(), "provisioner")
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningService.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningService.kt
deleted file mode 100644
index f64f9b5a..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningService.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.service
-
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.metal.driver.BareMetalDriver
-import kotlinx.coroutines.CancellationException
-
-/**
- * A very basic implementation of the [ProvisioningService].
- */
-public class SimpleProvisioningService : ProvisioningService {
- /**
- * The active nodes in this service.
- */
- private val nodes: MutableMap<Node, BareMetalDriver> = mutableMapOf()
-
- override suspend fun create(driver: BareMetalDriver): Node {
- val node = driver.init()
- nodes[node] = driver
- return node
- }
-
- override suspend fun nodes(): Set<Node> = nodes.keys
-
- override suspend fun refresh(node: Node): Node {
- return nodes[node]!!.refresh()
- }
-
- override suspend fun deploy(node: Node, image: Image): Node {
- val driver = nodes[node]!!
- driver.setImage(image)
- return driver.reboot()
- }
-
- override suspend fun stop(node: Node): Node {
- val driver = nodes[node]!!
- return try {
- driver.stop()
- } catch (e: CancellationException) {
- node
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/Hypervisor.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/Hypervisor.kt
deleted file mode 100644
index 69b0124d..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/Hypervisor.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt
-
-import com.atlarge.opendc.core.Identity
-import kotlinx.coroutines.flow.Flow
-import java.util.UUID
-
-/**
- * A hypervisor (or virtual machine monitor) is software or firmware that virtualizes the host compute environment
- * into several virtual guest machines.
- */
-public class Hypervisor(
- /**
- * The unique identifier of the hypervisor.
- */
- override val uid: UUID,
-
- /**
- * The optional name of the hypervisor.
- */
- override val name: String,
-
- /**
- * Metadata of the hypervisor.
- */
- public val metadata: Map<String, Any>,
-
- /**
- * The events that are emitted by the hypervisor.
- */
- public val events: Flow<HypervisorEvent>
-) : Identity {
- override fun hashCode(): Int = uid.hashCode()
- override fun equals(other: Any?): Boolean = other is Hypervisor && uid == other.uid
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorEvent.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorEvent.kt
deleted file mode 100644
index 7c088bc8..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorEvent.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt
-
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-
-/**
- * An event that is emitted by a [VirtDriver].
- */
-public sealed class HypervisorEvent {
- /**
- * The driver that emitted the event.
- */
- public abstract val driver: VirtDriver
-
- /**
- * This event is emitted when the number of active servers on the server managed by this driver is updated.
- *
- * @property driver The driver that emitted the event.
- * @property numberOfActiveServers The number of active servers.
- * @property availableMemory The available memory, in MB.
- */
- public data class VmsUpdated(
- override val driver: VirtDriver,
- public val numberOfActiveServers: Int,
- public val availableMemory: Long
- ) : HypervisorEvent()
-
- /**
- * This event is emitted when a slice is finished.
- *
- * @property driver The driver that emitted the event.
- * @property requestedBurst The total requested CPU time (can be above capacity).
- * @property grantedBurst The actual total granted capacity, which might be lower than the requested burst due to
- * the hypervisor being interrupted during a slice.
- * @property overcommissionedBurst The CPU time that the hypervisor could not grant to the virtual machine since
- * it did not have the capacity.
- * @property interferedBurst The sum of CPU time that virtual machines could not utilize due to performance
- * interference.
- * @property cpuUsage CPU use in megahertz.
- * @property cpuDemand CPU demand in megahertz.
- * @property numberOfDeployedImages The number of images deployed on this hypervisor.
- */
- public data class SliceFinished(
- override val driver: VirtDriver,
- public val requestedBurst: Long,
- public val grantedBurst: Long,
- public val overcommissionedBurst: Long,
- public val interferedBurst: Long,
- public val cpuUsage: Double,
- public val cpuDemand: Double,
- public val numberOfDeployedImages: Int,
- public val hostServer: Server
- ) : HypervisorEvent()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt
deleted file mode 100644
index bd395f0d..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/HypervisorImage.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt
-
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.virt.driver.SimpleVirtDriver
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.core.resource.TagContainer
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.suspendCancellableCoroutine
-import java.util.UUID
-
-/**
- * A hypervisor managing the VMs of a node.
- */
-object HypervisorImage : Image {
- override val uid: UUID = UUID.randomUUID()
- override val name: String = "vmm"
- override val tags: TagContainer = emptyMap()
-
- override suspend fun invoke(ctx: ServerContext) {
- coroutineScope {
- val driver = SimpleVirtDriver(ctx, this)
- ctx.publishService(VirtDriver.Key, driver)
-
- // Suspend image until it is cancelled
- try {
- suspendCancellableCoroutine<Unit> {}
- } finally {
- driver.cancel()
- }
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/InsufficientMemoryOnServerException.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/InsufficientMemoryOnServerException.kt
deleted file mode 100644
index 0586ae00..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/InsufficientMemoryOnServerException.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.atlarge.opendc.compute.virt.driver
-
-public class InsufficientMemoryOnServerException : IllegalStateException("Insufficient memory left on server.")
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/SimpleVirtDriver.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/SimpleVirtDriver.kt
deleted file mode 100644
index fa172e6e..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/SimpleVirtDriver.kt
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt.driver
-
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.execution.ServerContext
-import com.atlarge.opendc.compute.core.execution.ServerManagementContext
-import com.atlarge.opendc.compute.core.execution.ShutdownException
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.core.workload.IMAGE_PERF_INTERFERENCE_MODEL
-import com.atlarge.opendc.compute.core.workload.PerformanceInterferenceModel
-import com.atlarge.opendc.compute.virt.HypervisorEvent
-import com.atlarge.opendc.core.services.ServiceKey
-import com.atlarge.opendc.core.services.ServiceRegistry
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.intrinsics.startCoroutineCancellable
-import kotlinx.coroutines.selects.SelectClause0
-import kotlinx.coroutines.selects.SelectInstance
-import kotlinx.coroutines.selects.select
-import mu.KotlinLogging
-import org.opendc.utils.flow.EventFlow
-import java.time.Clock
-import java.util.UUID
-import kotlin.math.ceil
-import kotlin.math.max
-import kotlin.math.min
-
-/**
- * The logging instance to use.
- */
-private val logger = KotlinLogging.logger {}
-
-/**
- * A [VirtDriver] that is backed by a simple hypervisor implementation.
- */
-@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
-class SimpleVirtDriver(
- private val hostContext: ServerContext,
- scope: CoroutineScope
-) : VirtDriver, CoroutineScope by scope {
- /**
- * The [Server] on which this hypervisor runs.
- */
- val server: Server
- get() = hostContext.server
-
- /**
- * A set for tracking the VM context objects.
- */
- private val vms: MutableSet<VmServerContext> = mutableSetOf()
-
- /**
- * Current total memory use of the images on this hypervisor.
- */
- private var availableMemory: Long = hostContext.server.flavor.memorySize
-
- /**
- * The [EventFlow] to emit the events.
- */
- internal val eventFlow = EventFlow<HypervisorEvent>()
-
- override val events: Flow<HypervisorEvent> = eventFlow
-
- init {
- launch {
- try {
- // Yield first to allow class variables to initialize
- yield()
- scheduler()
- } catch (e: Exception) {
- if (e !is CancellationException) {
- logger.error("Hypervisor scheduler failed", e)
- }
- throw e
- }
- }
- }
-
- override suspend fun spawn(
- name: String,
- image: Image,
- flavor: Flavor
- ): Server {
- val requiredMemory = flavor.memorySize
- if (availableMemory - requiredMemory < 0) {
- throw InsufficientMemoryOnServerException()
- }
- require(flavor.cpuCount <= hostContext.server.flavor.cpuCount) { "Machine does not fit" }
-
- val events = EventFlow<ServerEvent>()
- val server = Server(
- UUID.randomUUID(),
- name,
- emptyMap(),
- flavor,
- image,
- ServerState.BUILD,
- ServiceRegistry(),
- events
- )
- availableMemory -= requiredMemory
- vms.add(VmServerContext(server, events))
- vmStarted(server)
- eventFlow.emit(HypervisorEvent.VmsUpdated(this, vms.size, availableMemory))
- return server
- }
-
- internal fun cancel() {
- eventFlow.close()
- }
-
- private fun vmStarted(server: Server) {
- vms.forEach {
- val performanceModel =
- it.server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel?
- performanceModel?.vmStarted(server)
- }
- }
-
- private fun vmStopped(server: Server) {
- vms.forEach {
- val performanceModel =
- it.server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel?
- performanceModel?.vmStopped(server)
- }
- }
-
- /**
- * A scheduling command processed by the scheduler.
- */
- private sealed class SchedulerCommand {
- /**
- * Schedule the specified VM on the hypervisor.
- */
- data class Schedule(val vm: Vm) : SchedulerCommand()
-
- /**
- * De-schedule the specified VM on the hypervisor.
- */
- data class Deschedule(val vm: Vm) : SchedulerCommand()
-
- /**
- * Interrupt the scheduler.
- */
- object Interrupt : SchedulerCommand()
- }
-
- /**
- * A flag to indicate the driver is stopped.
- */
- private var stopped: Boolean = false
-
- /**
- * The channel for scheduling new CPU requests.
- */
- private val schedulingQueue = Channel<SchedulerCommand>(Channel.UNLIMITED)
-
- /**
- * The scheduling process of the hypervisor.
- */
- private suspend fun scheduler() {
- val clock = hostContext.clock
- val maxUsage = hostContext.cpus.sumByDouble { it.frequency }
- val pCPUs = hostContext.cpus.indices.sortedBy { hostContext.cpus[it].frequency }
-
- val vms = mutableSetOf<Vm>()
- val vcpus = mutableListOf<VCpu>()
-
- val usage = DoubleArray(hostContext.cpus.size)
- val burst = LongArray(hostContext.cpus.size)
-
- fun process(command: SchedulerCommand) {
- when (command) {
- is SchedulerCommand.Schedule -> {
- vms += command.vm
- vcpus.addAll(command.vm.vcpus)
- }
- is SchedulerCommand.Deschedule -> {
- vms -= command.vm
- vcpus.removeAll(command.vm.vcpus)
- }
- is SchedulerCommand.Interrupt -> {}
- }
- }
-
- fun processRemaining() {
- var command = schedulingQueue.poll()
- while (command != null) {
- process(command)
- command = schedulingQueue.poll()
- }
- }
-
- while (!stopped) {
- // Wait for a request to be submitted if we have no work yet.
- if (vcpus.isEmpty()) {
- process(schedulingQueue.receive())
- }
-
- processRemaining()
-
- val start = clock.millis()
-
- val vmCount = vms.size
- var duration: Double = Double.POSITIVE_INFINITY
- var deadline: Long = Long.MAX_VALUE
- var availableUsage = maxUsage
- var totalRequestedUsage = 0.0
- var totalRequestedBurst = 0L
-
- // Sort the vCPUs based on their requested usage
- // Profiling shows that it is faster to sort every slice instead of maintaining some kind of sorted set
- vcpus.sort()
-
- // Divide the available host capacity fairly across the vCPUs using max-min fair sharing
- for ((i, req) in vcpus.withIndex()) {
- val remaining = vcpus.size - i
- val availableShare = availableUsage / remaining
- val grantedUsage = min(req.limit, availableShare)
-
- // Take into account the minimum deadline of this slice before we possible continue
- deadline = min(deadline, req.vm.deadline)
-
- // Ignore empty CPUs
- if (grantedUsage <= 0 || req.burst <= 0) {
- req.allocatedLimit = 0.0
- continue
- }
-
- totalRequestedUsage += req.limit
- totalRequestedBurst += req.burst
-
- req.allocatedLimit = grantedUsage
- availableUsage -= grantedUsage
-
- // The duration that we want to run is that of the shortest request from a vCPU
- duration = min(duration, req.burst / grantedUsage)
- }
-
- // XXX We set the minimum duration to 5 minutes here to prevent the rounding issues that are occurring with the FLOPs.
- duration = 300.0
-
- val totalAllocatedUsage = maxUsage - availableUsage
- var totalAllocatedBurst = 0L
- availableUsage = totalAllocatedUsage
- val serverLoad = totalAllocatedUsage / maxUsage
-
- // Divide the requests over the available capacity of the pCPUs fairly
- for (i in pCPUs) {
- val maxCpuUsage = hostContext.cpus[i].frequency
- val fraction = maxCpuUsage / maxUsage
- val grantedUsage = min(maxCpuUsage, totalAllocatedUsage * fraction)
- val grantedBurst = ceil(duration * grantedUsage).toLong()
-
- usage[i] = grantedUsage
- burst[i] = grantedBurst
- totalAllocatedBurst += grantedBurst
- availableUsage -= grantedUsage
- }
-
- // We run the total burst on the host processor. Note that this call may be cancelled at any moment in
- // time, so not all of the burst may be executed.
- select<Boolean> {
- schedulingQueue.onReceive { schedulingQueue.offer(it); true }
- hostContext.onRun(ServerContext.Slice(burst, usage, deadline), ServerContext.TriggerMode.DEADLINE).invoke { false }
- }
-
- val end = clock.millis()
-
- // No work was performed
- if ((end - start) <= 0) {
- continue
- }
-
- // The total requested burst that the VMs wanted to run in the time-frame that we ran.
- val totalRequestedSubBurst = vcpus.map { ceil((duration * 1000) / (it.vm.deadline - start) * it.burst).toLong() }.sum()
- val totalRemainder = burst.sum()
- val totalGrantedBurst = totalAllocatedBurst - totalRemainder
-
- // The burst that was lost due to overcommissioning of CPU resources
- var totalOvercommissionedBurst = 0L
- // The burst that was lost due to interference.
- var totalInterferedBurst = 0L
-
- val vmIterator = vms.iterator()
- while (vmIterator.hasNext()) {
- val vm = vmIterator.next()
-
- // Apply performance interference model
- val performanceModel =
- vm.ctx.server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel?
- val performanceScore = performanceModel?.apply(serverLoad) ?: 1.0
- var hasFinished = false
-
- for (vcpu in vm.vcpus) {
- // Compute the fraction of compute time allocated to the VM
- val fraction = vcpu.allocatedLimit / totalAllocatedUsage
-
- // Compute the burst time that the VM was actually granted
- val grantedBurst = ceil(totalGrantedBurst * fraction).toLong()
-
- // The burst that was actually used by the VM
- val usedBurst = ceil(grantedBurst * performanceScore).toLong()
-
- totalInterferedBurst += grantedBurst - usedBurst
-
- // Compute remaining burst time to be executed for the request
- if (vcpu.consume(usedBurst)) {
- hasFinished = true
- } else if (vm.deadline <= end && hostContext.server.state != ServerState.ERROR) {
- // Request must have its entire burst consumed or otherwise we have overcommission
- // Note that we count the overcommissioned burst if the hypervisor has failed.
- totalOvercommissionedBurst += vcpu.burst
- }
- }
-
- if (hasFinished || vm.deadline <= end) {
- // Mark the VM as finished and deschedule the VMs if needed
- if (vm.finish()) {
- vmIterator.remove()
- vcpus.removeAll(vm.vcpus)
- }
- }
- }
-
- eventFlow.emit(
- HypervisorEvent.SliceFinished(
- this@SimpleVirtDriver,
- totalRequestedBurst,
- min(totalRequestedSubBurst, totalGrantedBurst), // We can run more than requested due to timing
- totalOvercommissionedBurst,
- totalInterferedBurst, // Might be smaller than zero due to FP rounding errors,
- min(totalAllocatedUsage, totalRequestedUsage), // The allocated usage might be slightly higher due to FP rounding
- totalRequestedUsage,
- vmCount, // Some VMs might already have finished, so keep initial VM count
- server
- )
- )
- }
- }
-
- /**
- * A virtual machine running on the hypervisor.
- *
- * @param ctx The execution context the vCPU runs in.
- * @param triggerMode The mode when to trigger the VM exit.
- * @param merge The function to merge consecutive slices on spillover.
- * @param select The function to select on finish.
- */
- @OptIn(InternalCoroutinesApi::class)
- private data class Vm(
- val ctx: VmServerContext,
- var triggerMode: ServerContext.TriggerMode = ServerContext.TriggerMode.FIRST,
- var merge: (ServerContext.Slice, ServerContext.Slice) -> ServerContext.Slice = { _, r -> r },
- var select: () -> Unit = {}
- ) {
- /**
- * The vCPUs of this virtual machine.
- */
- val vcpus: List<VCpu>
-
- /**
- * The slices that the VM wants to run.
- */
- var queue: Iterator<ServerContext.Slice> = emptyList<ServerContext.Slice>().iterator()
-
- /**
- * The current active slice.
- */
- var activeSlice: ServerContext.Slice? = null
-
- /**
- * The current deadline of the VM.
- */
- val deadline: Long
- get() = activeSlice?.deadline ?: Long.MAX_VALUE
-
- /**
- * A flag to indicate that the VM is idle.
- */
- val isIdle: Boolean
- get() = activeSlice == null
-
- init {
- vcpus = ctx.cpus.mapIndexed { i, model -> VCpu(this, model, i) }
- }
-
- /**
- * Schedule the given slices on this vCPU, replacing the existing slices.
- */
- fun schedule(slices: Sequence<ServerContext.Slice>) {
- queue = slices.iterator()
-
- if (queue.hasNext()) {
- activeSlice = queue.next()
- vcpus.forEach { it.refresh() }
- }
- }
-
- /**
- * Cancel the existing workload on the VM.
- */
- fun cancel() {
- queue = emptyList<ServerContext.Slice>().iterator()
- activeSlice = null
- vcpus.forEach { it.refresh() }
- }
-
- /**
- * Finish the current slice of the VM.
- *
- * @return `true` if the vCPUs may be descheduled, `false` otherwise.
- */
- fun finish(): Boolean {
- val activeSlice = activeSlice ?: return true
-
- return if (queue.hasNext()) {
- val needsMerge = activeSlice.burst.any { it > 0 }
- val candidateSlice = queue.next()
- val slice = if (needsMerge) merge(activeSlice, candidateSlice) else candidateSlice
-
- this.activeSlice = slice
-
- // Update the vCPU cache
- vcpus.forEach { it.refresh() }
-
- false
- } else {
- this.activeSlice = null
- select()
- true
- }
- }
- }
-
- /**
- * A virtual CPU that can be scheduled on a physical CPU.
- *
- * @param vm The VM of which this vCPU is part.
- * @param model The model of CPU that this vCPU models.
- * @param id The id of the vCPU with respect to the VM.
- */
- private data class VCpu(
- val vm: Vm,
- val model: ProcessingUnit,
- val id: Int
- ) : Comparable<VCpu> {
- /**
- * The current limit on the vCPU.
- */
- var limit: Double = 0.0
-
- /**
- * The limit allocated by the hypervisor.
- */
- var allocatedLimit: Double = 0.0
-
- /**
- * The current burst running on the vCPU.
- */
- var burst: Long = 0L
-
- /**
- * Consume the specified burst on this vCPU.
- */
- fun consume(burst: Long): Boolean {
- this.burst = max(0, this.burst - burst)
-
- // Flush the result to the slice if it exists
- vm.activeSlice?.burst?.takeIf { id < it.size }?.set(id, this.burst)
-
- return allocatedLimit > 0.0 && this.burst == 0L
- }
-
- /**
- * Refresh the information of this vCPU based on the current slice.
- */
- fun refresh() {
- limit = vm.activeSlice?.limit?.takeIf { id < it.size }?.get(id) ?: 0.0
- burst = vm.activeSlice?.burst?.takeIf { id < it.size }?.get(id) ?: 0
- }
-
- /**
- * Compare to another vCPU based on the current load of the vCPU.
- */
- override fun compareTo(other: VCpu): Int {
- var cmp = limit.compareTo(other.limit)
-
- if (cmp != 0) {
- return cmp
- }
-
- cmp = vm.ctx.server.uid.compareTo(other.vm.ctx.server.uid)
-
- if (cmp != 0) {
- return cmp
- }
-
- return id.compareTo(other.id)
- }
-
- /**
- * Create a string representation of the vCPU.
- */
- override fun toString(): String =
- "vCPU(vm=${vm.ctx.server.uid},id=$id,burst=$burst,limit=$limit,allocatedLimit=$allocatedLimit)"
- }
-
- /**
- * The execution context in which a VM runs.
- *
- * @param server The details of the VM.
- * @param events The event stream to publish to.
- */
- private inner class VmServerContext(server: Server, val events: EventFlow<ServerEvent>) : ServerManagementContext, DisposableHandle {
- private var finalized: Boolean = false
- private var initialized: Boolean = false
- private val vm: Vm
-
- internal val job: Job = launch {
- delay(1) // TODO Introduce boot time
- init()
- try {
- server.image(this@VmServerContext)
- exit()
- } catch (cause: Throwable) {
- exit(cause)
- }
- }
-
- override var server: Server = server
- set(value) {
- if (field.state != value.state) {
- events.emit(ServerEvent.StateChanged(value, field.state))
- }
-
- field = value
- }
-
- override val cpus: List<ProcessingUnit> = hostContext.cpus.take(server.flavor.cpuCount)
-
- override val clock: Clock
- get() = hostContext.clock
-
- init {
- vm = Vm(this)
- }
-
- override suspend fun <T : Any> publishService(key: ServiceKey<T>, service: T) {
- server = server.copy(services = server.services.put(key, service))
- events.emit(ServerEvent.ServicePublished(server, key))
- }
-
- override suspend fun init() {
- assert(!finalized) { "VM is already finalized" }
-
- server = server.copy(state = ServerState.ACTIVE)
- initialized = true
- }
-
- override suspend fun exit(cause: Throwable?) {
- finalized = true
-
- val serverState =
- if (cause == null || (cause is ShutdownException && cause.cause == null))
- ServerState.SHUTOFF
- else
- ServerState.ERROR
- server = server.copy(state = serverState)
- availableMemory += server.flavor.memorySize
- vms.remove(this)
- vmStopped(server)
- eventFlow.emit(HypervisorEvent.VmsUpdated(this@SimpleVirtDriver, vms.size, availableMemory))
- events.close()
- }
-
- @OptIn(InternalCoroutinesApi::class)
- override fun onRun(
- batch: Sequence<ServerContext.Slice>,
- triggerMode: ServerContext.TriggerMode,
- merge: (ServerContext.Slice, ServerContext.Slice) -> ServerContext.Slice
- ): SelectClause0 = object : SelectClause0 {
- @InternalCoroutinesApi
- override fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R) {
- vm.triggerMode = triggerMode
- vm.merge = merge
- vm.select = {
- if (select.trySelect()) {
- block.startCoroutineCancellable(select.completion)
- }
- }
- vm.schedule(batch)
- // Indicate to the hypervisor that the VM should be re-scheduled
- schedulingQueue.offer(SchedulerCommand.Schedule(vm))
- select.disposeOnSelect(this@VmServerContext)
- }
- }
-
- override fun dispose() {
- if (!vm.isIdle) {
- vm.cancel()
- schedulingQueue.offer(SchedulerCommand.Deschedule(vm))
- }
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt
deleted file mode 100644
index 1002d382..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/VirtDriver.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt.driver
-
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.virt.HypervisorEvent
-import com.atlarge.opendc.core.services.AbstractServiceKey
-import kotlinx.coroutines.flow.Flow
-import java.util.UUID
-
-/**
- * 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 {
- /**
- * The events emitted by the driver.
- */
- public val events: Flow<HypervisorEvent>
-
- /**
- * Spawn the given [Image] on the compute resource of this driver.
- *
- * @param name The name of the server to spawn.
- * @param image The image to deploy.
- * @param flavor The flavor of the server which this driver is controlling.
- * @return The virtual server spawned by this method.
- */
- public suspend fun spawn(name: String, image: Image, flavor: Flavor): Server
-
- companion object Key : AbstractServiceKey<VirtDriver>(UUID.randomUUID(), "virtual-driver")
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt
deleted file mode 100644
index e52a1698..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/HypervisorView.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.atlarge.opendc.compute.virt.service
-
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import java.util.UUID
-
-class HypervisorView(
- val uid: UUID,
- var server: Server,
- var numberOfActiveServers: Int,
- var availableMemory: Long,
- var provisionedCores: Int
-) {
- lateinit var driver: VirtDriver
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt
deleted file mode 100644
index 5e151cbb..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/SimpleVirtProvisioningService.kt
+++ /dev/null
@@ -1,358 +0,0 @@
-package com.atlarge.opendc.compute.virt.service
-
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.metal.service.ProvisioningService
-import com.atlarge.opendc.compute.virt.HypervisorEvent
-import com.atlarge.opendc.compute.virt.HypervisorImage
-import com.atlarge.opendc.compute.virt.driver.InsufficientMemoryOnServerException
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.compute.virt.service.allocation.AllocationPolicy
-import com.atlarge.opendc.core.services.ServiceKey
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import mu.KotlinLogging
-import org.opendc.utils.flow.EventFlow
-import java.time.Clock
-import kotlin.coroutines.Continuation
-import kotlin.coroutines.resume
-import kotlin.math.max
-
-private val logger = KotlinLogging.logger {}
-
-@OptIn(ExperimentalCoroutinesApi::class)
-class SimpleVirtProvisioningService(
- private val coroutineScope: CoroutineScope,
- private val clock: Clock,
- private val provisioningService: ProvisioningService,
- override val allocationPolicy: AllocationPolicy
-) : VirtProvisioningService {
- /**
- * The hypervisors that have been launched by the service.
- */
- private val hypervisors: MutableMap<Server, HypervisorView> = mutableMapOf()
-
- /**
- * The available hypervisors.
- */
- private val availableHypervisors: MutableSet<HypervisorView> = mutableSetOf()
-
- /**
- * The incoming images to be processed by the provisioner.
- */
- private val incomingImages: MutableSet<ImageView> = mutableSetOf()
-
- /**
- * The active images in the system.
- */
- private val activeImages: MutableSet<ImageView> = mutableSetOf()
-
- var submittedVms = 0
- var queuedVms = 0
- var runningVms = 0
- var finishedVms = 0
- var unscheduledVms = 0
-
- private var maxCores = 0
- private var maxMemory = 0L
-
- /**
- * The allocation logic to use.
- */
- private val allocationLogic = allocationPolicy()
-
- /**
- * The [EventFlow] to emit the events.
- */
- internal val eventFlow = EventFlow<VirtProvisioningEvent>()
-
- override val events: Flow<VirtProvisioningEvent> = eventFlow
-
- init {
- coroutineScope.launch {
- val provisionedNodes = provisioningService.nodes()
- provisionedNodes.forEach { node ->
- val hypervisorImage = HypervisorImage
- val node = provisioningService.deploy(node, hypervisorImage)
- node.server!!.events.onEach { event ->
- when (event) {
- is ServerEvent.StateChanged -> stateChanged(event.server)
- is ServerEvent.ServicePublished -> servicePublished(event.server, event.key)
- }
- }.launchIn(this)
- }
- }
- }
-
- override suspend fun drivers(): Set<VirtDriver> {
- return availableHypervisors.map { it.driver }.toSet()
- }
-
- override suspend fun deploy(
- name: String,
- image: Image,
- flavor: Flavor
- ): Server {
- eventFlow.emit(
- VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- ++submittedVms,
- runningVms,
- finishedVms,
- ++queuedVms,
- unscheduledVms
- )
- )
-
- return suspendCancellableCoroutine<Server> { cont ->
- val vmInstance = ImageView(name, image, flavor, cont)
- incomingImages += vmInstance
- requestCycle()
- }
- }
-
- override suspend fun terminate() {
- val provisionedNodes = provisioningService.nodes()
- provisionedNodes.forEach { node -> provisioningService.stop(node) }
- }
-
- private var call: Job? = null
-
- private fun requestCycle() {
- if (call != null) {
- return
- }
-
- val quantum = 300000 // 5 minutes in milliseconds
- // We assume that the provisioner runs at a fixed slot every time quantum (e.g t=0, t=60, t=120).
- // This is important because the slices of the VMs need to be aligned.
- // We calculate here the delay until the next scheduling slot.
- val delay = quantum - (clock.millis() % quantum)
-
- val call = coroutineScope.launch {
- delay(delay)
- this@SimpleVirtProvisioningService.call = null
- schedule()
- }
- this.call = call
- }
-
- private suspend fun schedule() {
- val imagesToBeScheduled = incomingImages.toSet()
-
- for (imageInstance in imagesToBeScheduled) {
- val requiredMemory = (imageInstance.image as VmImage).requiredMemory
- val selectedHv = allocationLogic.select(availableHypervisors, imageInstance)
-
- if (selectedHv == null) {
- if (requiredMemory > maxMemory || imageInstance.flavor.cpuCount > maxCores) {
- eventFlow.emit(
- VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- ++unscheduledVms
- )
- )
-
- incomingImages -= imageInstance
-
- logger.warn("Failed to spawn ${imageInstance.image}: does not fit [${clock.millis()}]")
- continue
- } else {
- break
- }
- }
-
- try {
- logger.info { "[${clock.millis()}] Spawning ${imageInstance.image} on ${selectedHv.server.uid} ${selectedHv.server.name} ${selectedHv.server.flavor}" }
- incomingImages -= imageInstance
-
- // Speculatively update the hypervisor view information to prevent other images in the queue from
- // deciding on stale values.
- selectedHv.numberOfActiveServers++
- selectedHv.provisionedCores += imageInstance.flavor.cpuCount
- selectedHv.availableMemory -= requiredMemory // XXX Temporary hack
-
- val server = selectedHv.driver.spawn(
- imageInstance.name,
- imageInstance.image,
- imageInstance.flavor
- )
- imageInstance.server = server
- imageInstance.continuation.resume(server)
-
- eventFlow.emit(
- VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- ++runningVms,
- finishedVms,
- --queuedVms,
- unscheduledVms
- )
- )
- activeImages += imageInstance
-
- server.events
- .onEach { event ->
- when (event) {
- is ServerEvent.StateChanged -> {
- if (event.server.state == ServerState.SHUTOFF) {
- logger.info { "[${clock.millis()}] Server ${event.server.uid} ${event.server.name} ${event.server.flavor} finished." }
-
- eventFlow.emit(
- VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- --runningVms,
- ++finishedVms,
- queuedVms,
- unscheduledVms
- )
- )
-
- activeImages -= imageInstance
- selectedHv.provisionedCores -= server.flavor.cpuCount
-
- // Try to reschedule if needed
- if (incomingImages.isNotEmpty()) {
- requestCycle()
- }
- }
- }
- }
- }
- .launchIn(coroutineScope)
- } catch (e: InsufficientMemoryOnServerException) {
- logger.error("Failed to deploy VM", e)
-
- selectedHv.numberOfActiveServers--
- selectedHv.provisionedCores -= imageInstance.flavor.cpuCount
- selectedHv.availableMemory += requiredMemory
- } catch (e: Throwable) {
- logger.error("Failed to deploy VM", e)
- }
- }
- }
-
- private fun stateChanged(server: Server) {
- when (server.state) {
- ServerState.ACTIVE -> {
- logger.debug { "[${clock.millis()}] Server ${server.uid} available: ${server.state}" }
-
- if (server in hypervisors) {
- // Corner case for when the hypervisor already exists
- availableHypervisors += hypervisors.getValue(server)
- } else {
- val hv = HypervisorView(
- server.uid,
- server,
- 0,
- server.flavor.memorySize,
- 0
- )
- maxCores = max(maxCores, server.flavor.cpuCount)
- maxMemory = max(maxMemory, server.flavor.memorySize)
- hypervisors[server] = hv
- }
-
- eventFlow.emit(
- VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- unscheduledVms
- )
- )
-
- // Re-schedule on the new machine
- if (incomingImages.isNotEmpty()) {
- requestCycle()
- }
- }
- ServerState.SHUTOFF, ServerState.ERROR -> {
- logger.debug { "[${clock.millis()}] Server ${server.uid} unavailable: ${server.state}" }
- val hv = hypervisors[server] ?: return
- availableHypervisors -= hv
-
- eventFlow.emit(
- VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- unscheduledVms
- )
- )
-
- if (incomingImages.isNotEmpty()) {
- requestCycle()
- }
- }
- else -> throw IllegalStateException()
- }
- }
-
- private fun servicePublished(server: Server, key: ServiceKey<*>) {
- if (key == VirtDriver.Key) {
- val hv = hypervisors[server] ?: return
- hv.driver = server.services[VirtDriver]
- availableHypervisors += hv
-
- eventFlow.emit(
- VirtProvisioningEvent.MetricsAvailable(
- this@SimpleVirtProvisioningService,
- hypervisors.size,
- availableHypervisors.size,
- submittedVms,
- runningVms,
- finishedVms,
- queuedVms,
- unscheduledVms
- )
- )
-
- hv.driver.events
- .onEach { event ->
- if (event is HypervisorEvent.VmsUpdated) {
- hv.numberOfActiveServers = event.numberOfActiveServers
- hv.availableMemory = event.availableMemory
- }
- }.launchIn(coroutineScope)
-
- requestCycle()
- }
- }
-
- data class ImageView(
- val name: String,
- val image: Image,
- val flavor: Flavor,
- val continuation: Continuation<Server>,
- var server: Server? = null
- )
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningEvent.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningEvent.kt
deleted file mode 100644
index c3fb99f9..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningEvent.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt.service
-
-/**
- * An event that is emitted by the [VirtProvisioningService].
- */
-public sealed class VirtProvisioningEvent {
- /**
- * The service that has emitted the event.
- */
- public abstract val provisioner: VirtProvisioningService
-
- /**
- * An event emitted for writing metrics.
- */
- data class MetricsAvailable(
- override val provisioner: VirtProvisioningService,
- public val totalHostCount: Int,
- public val availableHostCount: Int,
- public val totalVmCount: Int,
- public val activeVmCount: Int,
- public val inactiveVmCount: Int,
- public val waitingVmCount: Int,
- public val failedVmCount: Int
- ) : VirtProvisioningEvent()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt
deleted file mode 100644
index c4cbd711..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/VirtProvisioningService.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.atlarge.opendc.compute.virt.service
-
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.Server
-import com.atlarge.opendc.compute.core.image.Image
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import com.atlarge.opendc.compute.virt.service.allocation.AllocationPolicy
-import kotlinx.coroutines.flow.Flow
-
-/**
- * A service for VM provisioning on a cloud.
- */
-interface VirtProvisioningService {
- /**
- * The policy used for allocating a VM on the available hypervisors.
- */
- val allocationPolicy: AllocationPolicy
-
- /**
- * The events emitted by the service.
- */
- public val events: Flow<VirtProvisioningEvent>
-
- /**
- * Obtain the active hypervisors for this provisioner.
- */
- public suspend fun drivers(): Set<VirtDriver>
-
- /**
- * Submit the specified [Image] to the provisioning service.
- *
- * @param name The name of the server to deploy.
- * @param image The image to be deployed.
- * @param flavor The flavor of the machine instance to run this [image] on.
- */
- public suspend fun deploy(name: String, image: Image, flavor: Flavor): Server
-
- /**
- * Terminate the provisioning service releasing all the leased bare-metal machines.
- */
- public suspend fun terminate()
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt
deleted file mode 100644
index b7c9388d..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AllocationPolicy.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.metal.Node
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-
-/**
- * A policy for selecting the [Node] an image should be deployed to,
- */
-public interface AllocationPolicy {
- /**
- * The logic of the allocation policy.
- */
- public interface Logic {
- /**
- * Select the node on which the server should be scheduled.
- */
- public fun select(hypervisors: Set<HypervisorView>, image: SimpleVirtProvisioningService.ImageView): HypervisorView?
- }
-
- /**
- * Builds the logic of the policy.
- */
- operator fun invoke(): Logic
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableCoreMemoryAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableCoreMemoryAllocationPolicy.kt
deleted file mode 100644
index 79b622d2..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableCoreMemoryAllocationPolicy.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-
-/**
- * An [AllocationPolicy] that selects the machine with the highest/lowest amount of memory per core.
- *
- * @param reversed An option to reverse the order of the machines (lower amount of memory scores better).
- */
-public class AvailableCoreMemoryAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
- override val comparator: Comparator<HypervisorView> =
- compareBy<HypervisorView> { -it.availableMemory / it.server.flavor.cpuCount }
- .run { if (reversed) reversed() else this }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt
deleted file mode 100644
index c081244f..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/AvailableMemoryAllocationPolicy.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-
-/**
- * Allocation policy that selects the node with the most available memory.
- *
- * @param reversed A flag to reverse the order (least amount of memory scores the best).
- */
-public class AvailableMemoryAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
- override val comparator: Comparator<HypervisorView> = compareBy<HypervisorView> { -it.availableMemory }
- .run { if (reversed) reversed() else this }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ComparableAllocationPolicyLogic.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ComparableAllocationPolicyLogic.kt
deleted file mode 100644
index 79dd95f3..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ComparableAllocationPolicyLogic.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-
-/**
- * The logic for an [AllocationPolicy] that uses a [Comparator] to select the appropriate node.
- */
-interface ComparableAllocationPolicyLogic : AllocationPolicy.Logic {
- /**
- * The comparator to use.
- */
- public val comparator: Comparator<HypervisorView>
-
- override fun select(
- hypervisors: Set<HypervisorView>,
- image: SimpleVirtProvisioningService.ImageView
- ): HypervisorView? {
- return hypervisors.asSequence()
- .filter { hv ->
- val fitsMemory = hv.availableMemory >= (image.image as VmImage).requiredMemory
- val fitsCpu = hv.server.flavor.cpuCount >= image.flavor.cpuCount
- fitsMemory && fitsCpu
- }
- .minWith(comparator.thenBy { it.server.uid })
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt
deleted file mode 100644
index 7e3e5864..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/NumberOfActiveServersAllocationPolicy.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-
-/**
- * Allocation policy that selects the node with the least amount of active servers.
- *
- * @param reversed A flag to reverse the order, such that the node with the most active servers is selected.
- */
-public class NumberOfActiveServersAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
- override val comparator: Comparator<HypervisorView> = compareBy<HypervisorView> { it.numberOfActiveServers }
- .run { if (reversed) reversed() else this }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ProvisionedCoresAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ProvisionedCoresAllocationPolicy.kt
deleted file mode 100644
index e1a995a0..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ProvisionedCoresAllocationPolicy.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-
-/**
- * An [AllocationPolicy] that takes into account the number of vCPUs that have been provisioned on this machine
- * relative to its core count.
- *
- * @param reversed A flag to reverse the order of the policy, such that the machine with the most provisioned cores
- * is selected.
- */
-class ProvisionedCoresAllocationPolicy(val reversed: Boolean = false) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : ComparableAllocationPolicyLogic {
- override val comparator: Comparator<HypervisorView> =
- compareBy<HypervisorView> { it.provisionedCores / it.server.flavor.cpuCount }
- .run { if (reversed) reversed() else this }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/RandomAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/RandomAllocationPolicy.kt
deleted file mode 100644
index 07dcf1c5..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/RandomAllocationPolicy.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-import kotlin.random.Random
-
-/**
- * An [AllocationPolicy] that select a random node on which the server fits.
- */
-public class RandomAllocationPolicy(val random: Random = Random(0)) : AllocationPolicy {
- @OptIn(ExperimentalStdlibApi::class)
- override fun invoke(): AllocationPolicy.Logic = object : AllocationPolicy.Logic {
- override fun select(
- hypervisors: Set<HypervisorView>,
- image: SimpleVirtProvisioningService.ImageView
- ): HypervisorView? {
- return hypervisors.asIterable()
- .filter { hv ->
- val fitsMemory = hv.availableMemory >= (image.image as VmImage).requiredMemory
- val fitsCpu = hv.server.flavor.cpuCount >= image.flavor.cpuCount
- fitsMemory && fitsCpu
- }
- .randomOrNull(random)
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt b/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt
deleted file mode 100644
index 59acfce2..00000000
--- a/simulator/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/service/allocation/ReplayAllocationPolicy.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.atlarge.opendc.compute.virt.service.allocation
-
-import com.atlarge.opendc.compute.virt.service.HypervisorView
-import com.atlarge.opendc.compute.virt.service.SimpleVirtProvisioningService
-import mu.KotlinLogging
-
-private val logger = KotlinLogging.logger {}
-
-/**
- * Policy replaying VM-cluster assignment.
- *
- * Within each cluster, the active servers on each node determine which node gets
- * assigned the VM image.
- */
-class ReplayAllocationPolicy(val vmPlacements: Map<String, String>) : AllocationPolicy {
- override fun invoke(): AllocationPolicy.Logic = object : AllocationPolicy.Logic {
- override fun select(
- hypervisors: Set<HypervisorView>,
- image: SimpleVirtProvisioningService.ImageView
- ): HypervisorView? {
- val clusterName = vmPlacements[image.name]
- ?: throw IllegalStateException("Could not find placement data in VM placement file for VM ${image.name}")
- val machinesInCluster = hypervisors.filter { it.server.name.contains(clusterName) }
-
- if (machinesInCluster.isEmpty()) {
- logger.info { "Could not find any machines belonging to cluster $clusterName for image ${image.name}, assigning randomly." }
- return hypervisors.maxBy { it.availableMemory }
- }
-
- return machinesInCluster.maxBy { it.availableMemory }
- ?: throw IllegalStateException("Cloud not find any machine and could not randomly assign")
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImageTest.kt b/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImageTest.kt
deleted file mode 100644
index 417db77d..00000000
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/core/image/FlopsApplicationImageTest.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.core.image
-
-import org.junit.jupiter.api.DisplayName
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import java.util.UUID
-
-/**
- * Test suite for [FlopsApplicationImage]
- */
-@DisplayName("FlopsApplicationImage")
-internal class FlopsApplicationImageTest {
- @Test
- fun `flops must be non-negative`() {
- assertThrows<IllegalArgumentException>("FLOPs must be non-negative") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), -1, 1)
- }
- }
-
- @Test
- fun `cores cannot be zero`() {
- assertThrows<IllegalArgumentException>("Cores cannot be zero") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 0)
- }
- }
-
- @Test
- fun `cores cannot be negative`() {
- assertThrows<IllegalArgumentException>("Cores cannot be negative") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, -1)
- }
- }
-
- @Test
- fun `utilization cannot be zero`() {
- assertThrows<IllegalArgumentException>("Utilization cannot be zero") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 1, 0.0)
- }
- }
-
- @Test
- fun `utilization cannot be negative`() {
- assertThrows<IllegalArgumentException>("Utilization cannot be negative") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 1, -1.0)
- }
- }
-
- @Test
- fun `utilization cannot be larger than one`() {
- assertThrows<IllegalArgumentException>("Utilization cannot be larger than one") {
- FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1, 1, 2.0)
- }
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt b/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt
deleted file mode 100644
index 7b57327e..00000000
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriverTest.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.driver
-
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.ServerEvent
-import com.atlarge.opendc.compute.core.ServerState
-import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestCoroutineScope
-import kotlinx.coroutines.withContext
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import org.opendc.simulator.utils.DelayControllerClockAdapter
-import java.util.UUID
-
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class SimpleBareMetalDriverTest {
- /**
- * A smoke test for the bare-metal driver.
- */
- @Test
- fun smoke() {
- val testScope = TestCoroutineScope()
- val clock = DelayControllerClockAdapter(testScope)
-
- var finalState: ServerState = ServerState.BUILD
- testScope.launch {
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
- val cpus = List(4) { ProcessingUnit(cpuNode, it, 2400.0) }
- val driver = SimpleBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
- val image = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1_000, 2)
-
- // Batch driver commands
- withContext(coroutineContext) {
- driver.init()
- driver.setImage(image)
- val server = driver.start().server!!
- driver.usage
- .onEach { println("${clock.millis()} $it") }
- .launchIn(this)
- server.events.collect { event ->
- when (event) {
- is ServerEvent.StateChanged -> {
- println("${clock.millis()} $event")
- finalState = event.server.state
- }
- }
- }
- }
- }
-
- testScope.advanceUntilIdle()
- assertEquals(ServerState.SHUTOFF, finalState)
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt b/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt
deleted file mode 100644
index 0a85e0f9..00000000
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/metal/service/SimpleProvisioningServiceTest.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.metal.service
-
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestCoroutineScope
-import org.junit.jupiter.api.Test
-import org.opendc.simulator.utils.DelayControllerClockAdapter
-import java.util.UUID
-
-/**
- * Test suite for the [SimpleProvisioningService].
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class SimpleProvisioningServiceTest {
- /**
- * A basic smoke test.
- */
- @Test
- fun smoke() {
- val testScope = TestCoroutineScope()
- val clock = DelayControllerClockAdapter(testScope)
-
- testScope.launch {
- val image = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1000, 2)
-
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 4)
- val cpus = List(4) { ProcessingUnit(cpuNode, it, 2400.0) }
- val driver = SimpleBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
-
- val provisioner = SimpleProvisioningService()
- provisioner.create(driver)
- delay(5)
- val nodes = provisioner.nodes()
- val node = provisioner.deploy(nodes.first(), image)
- node.server!!.events.collect { println(it) }
- }
-
- testScope.advanceUntilIdle()
- }
-}
diff --git a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt b/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt
deleted file mode 100644
index dca0b292..00000000
--- a/simulator/opendc/opendc-compute/src/test/kotlin/com/atlarge/opendc/compute/virt/HypervisorTest.kt
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2020 atlarge-research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package com.atlarge.opendc.compute.virt
-
-import com.atlarge.opendc.compute.core.Flavor
-import com.atlarge.opendc.compute.core.ProcessingNode
-import com.atlarge.opendc.compute.core.ProcessingUnit
-import com.atlarge.opendc.compute.core.image.FlopsApplicationImage
-import com.atlarge.opendc.compute.core.image.FlopsHistoryFragment
-import com.atlarge.opendc.compute.core.image.VmImage
-import com.atlarge.opendc.compute.metal.driver.SimpleBareMetalDriver
-import com.atlarge.opendc.compute.virt.driver.VirtDriver
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestCoroutineScope
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Disabled
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertAll
-import org.opendc.simulator.utils.DelayControllerClockAdapter
-import java.util.UUID
-
-/**
- * Basic test-suite for the hypervisor.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class HypervisorTest {
- /**
- * A smoke test for the bare-metal driver.
- */
- @OptIn(ExperimentalCoroutinesApi::class)
- @Test
- @Disabled
- fun smoke() {
- val testScope = TestCoroutineScope()
- val clock = DelayControllerClockAdapter(testScope)
-
- testScope.launch {
- val vmm = HypervisorImage
- val workloadA = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 1_000, 1)
- val workloadB = FlopsApplicationImage(UUID.randomUUID(), "<unnamed>", emptyMap(), 2_000, 1)
-
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1)
- val cpus = List(1) { ProcessingUnit(cpuNode, it, 2000.0) }
- val metalDriver = SimpleBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
-
- metalDriver.init()
- metalDriver.setImage(vmm)
- val node = metalDriver.start()
- node.server?.events?.onEach { println(it) }?.launchIn(this)
-
- delay(5)
-
- val flavor = Flavor(1, 0)
- val vmDriver = metalDriver.refresh().server!!.services[VirtDriver]
- vmDriver.events.onEach { println(it) }.launchIn(this)
- val vmA = vmDriver.spawn("a", workloadA, flavor)
- vmA.events.onEach { println(it) }.launchIn(this)
- val vmB = vmDriver.spawn("b", workloadB, flavor)
- vmB.events.onEach { println(it) }.launchIn(this)
- }
-
- testScope.advanceUntilIdle()
- }
-
- /**
- * Test overcommissioning of a hypervisor.
- */
- @Test
- fun overcommission() {
- val testScope = TestCoroutineScope()
- val clock = DelayControllerClockAdapter(testScope)
-
- var requestedBurst = 0L
- var grantedBurst = 0L
- var overcommissionedBurst = 0L
-
- testScope.launch {
- val vmm = HypervisorImage
- val duration = 5 * 60L
- val vmImageA = VmImage(
- UUID.randomUUID(),
- "<unnamed>",
- emptyMap(),
- sequenceOf(
- FlopsHistoryFragment(0, 28L * duration, duration * 1000, 28.0, 2),
- FlopsHistoryFragment(0, 3500L * duration, duration * 1000, 3500.0, 2),
- FlopsHistoryFragment(0, 0, duration * 1000, 0.0, 2),
- FlopsHistoryFragment(0, 183L * duration, duration * 1000, 183.0, 2)
- ),
- 2,
- 0
- )
- val vmImageB = VmImage(
- UUID.randomUUID(),
- "<unnamed>",
- emptyMap(),
- sequenceOf(
- FlopsHistoryFragment(0, 28L * duration, duration * 1000, 28.0, 2),
- FlopsHistoryFragment(0, 3100L * duration, duration * 1000, 3100.0, 2),
- FlopsHistoryFragment(0, 0, duration * 1000, 0.0, 2),
- FlopsHistoryFragment(0, 73L * duration, duration * 1000, 73.0, 2)
- ),
- 2,
- 0
- )
-
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
- val cpus = List(2) { ProcessingUnit(cpuNode, it, 3200.0) }
- val metalDriver = SimpleBareMetalDriver(this, clock, UUID.randomUUID(), "test", emptyMap(), cpus, emptyList())
-
- metalDriver.init()
- metalDriver.setImage(vmm)
- metalDriver.start()
-
- delay(5)
-
- val flavor = Flavor(2, 0)
- val vmDriver = metalDriver.refresh().server!!.services[VirtDriver]
- vmDriver.events
- .onEach { event ->
- when (event) {
- is HypervisorEvent.SliceFinished -> {
- requestedBurst += event.requestedBurst
- grantedBurst += event.grantedBurst
- overcommissionedBurst += event.overcommissionedBurst
- }
- }
- }
- .launchIn(this)
-
- vmDriver.spawn("a", vmImageA, flavor)
- vmDriver.spawn("b", vmImageB, flavor)
- }
-
- testScope.advanceUntilIdle()
-
- assertAll(
- { assertEquals(2073600, requestedBurst, "Requested Burst does not match") },
- { assertEquals(2013600, grantedBurst, "Granted Burst does not match") },
- { assertEquals(60000, overcommissionedBurst, "Overcommissioned Burst does not match") }
- )
- }
-}