diff options
6 files changed, 175 insertions, 3 deletions
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt index 99f9397d..139c66e0 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt @@ -30,6 +30,7 @@ import org.opendc.simulator.compute.device.SimPeripheral import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.model.MemoryUnit import org.opendc.simulator.compute.model.NetworkAdapter +import org.opendc.simulator.compute.model.StorageDevice import org.opendc.simulator.compute.workload.SimWorkload import org.opendc.simulator.resources.* import kotlin.coroutines.Continuation @@ -77,6 +78,11 @@ public abstract class SimAbstractMachine( protected val net: List<SimNetworkInterface> = model.net.mapIndexed { i, adapter -> NetworkAdapterImpl(adapter, i) } /** + * The network interfaces available to the machine. + */ + protected val storage: List<SimStorageInterface> = model.storage.mapIndexed { i, device -> StorageDeviceImpl(interpreter, device, i) } + + /** * The peripherals of the machine. */ public override val peripherals: List<SimPeripheral> = net.map { it as SimNetworkAdapter } @@ -181,6 +187,8 @@ public abstract class SimAbstractMachine( override val net: List<SimNetworkInterface> = this@SimAbstractMachine.net + override val storage: List<SimStorageInterface> = this@SimAbstractMachine.storage + override fun close() = cancel() } @@ -217,4 +225,23 @@ public abstract class SimAbstractMachine( override fun toString(): String = "SimAbstractMachine.NetworkAdapterImpl[name=$name,bandwidth=$bandwidth]" } + + /** + * The [SimStorageInterface] implementation for a machine. + */ + private class StorageDeviceImpl( + interpreter: SimResourceInterpreter, + model: StorageDevice, + index: Int + ) : SimStorageInterface { + override val name: String = "disk$index" + + override val capacity: Double = model.capacity + + override val read: SimResourceProvider = SimResourceSource(model.readBandwidth, interpreter) + + override val write: SimResourceProvider = SimResourceSource(model.writeBandwidth, interpreter) + + override fun toString(): String = "SimAbstractMachine.StorageDeviceImpl[name=$name,capacity=$capacity]" + } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt index 68a7fb63..6996a30d 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachineContext.kt @@ -56,6 +56,11 @@ public interface SimMachineContext : AutoCloseable { public val net: List<SimNetworkInterface> /** + * The storage devices available to the workload. + */ + public val storage: List<SimStorageInterface> + + /** * Stop the workload. */ public override fun close() diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimStorageInterface.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimStorageInterface.kt new file mode 100644 index 00000000..21a801f1 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimStorageInterface.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute + +import org.opendc.simulator.resources.SimResourceProvider + +/** + * A firmware interface to a storage device. + */ +public interface SimStorageInterface { + /** + * The name of the storage device. + */ + public val name: String + + /** + * The capacity of the storage device in MBs. + */ + public val capacity: Double + + /** + * The resource provider for the read operations of the storage device. + */ + public val read: SimResourceProvider + + /** + * The resource consumer for the write operation of the storage device. + */ + public val write: SimResourceProvider +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt index d40aff53..7e4d7191 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt @@ -27,10 +27,12 @@ package org.opendc.simulator.compute.model * * @property cpus The list of processing units available to the image. * @property memory The list of memory units available to the image. - * @property net A list of network adapters available for the machine. + * @property net A list of network adapters available to the machine. + * @property storage A list of storage devices available to the machine. */ public data class MachineModel( public val cpus: List<ProcessingUnit>, public val memory: List<MemoryUnit>, - public val net: List<NetworkAdapter> = emptyList() + public val net: List<NetworkAdapter> = emptyList(), + public val storage: List<StorageDevice> = emptyList() ) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/StorageDevice.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/StorageDevice.kt new file mode 100644 index 00000000..2621ad6d --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/StorageDevice.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.model + +/** + * Model for a physical storage device attached to a machine. + * + * @property vendor The vendor of the storage device. + * @property modelName The model name of the device. + * @property capacity The capacity of the device. + * @property readBandwidth The read bandwidth of the device in MBps. + * @property writeBandwidth The write bandwidth of the device in MBps. + */ +public data class StorageDevice( + public val vendor: String, + public val modelName: String, + public val capacity: Double, + public val readBandwidth: Double, + public val writeBandwidth: Double +) diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt index 47ae119c..892d5223 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt @@ -58,7 +58,8 @@ class SimMachineTest { machineModel = MachineModel( cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, - net = listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)) + net = listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)), + storage = listOf(StorageDevice("Samsung", "EVO", 1000.0, 250.0, 250.0)) ) } @@ -260,6 +261,53 @@ class SimMachineTest { } @Test + fun testDiskReadUsage() = runBlockingSimulation { + val interpreter = SimResourceInterpreter(coroutineContext, clock) + val machine = SimBareMetalMachine( + interpreter, + machineModel, + SimplePowerDriver(ConstantPowerModel(0.0)) + ) + + try { + machine.run(object : SimWorkload { + override fun onStart(ctx: SimMachineContext) { + val lifecycle = SimWorkloadLifecycle(ctx) + val disk = ctx.storage[0] + disk.read.startConsumer(lifecycle.waitFor(SimWorkConsumer(disk.read.capacity, utilization = 0.8))) + } + }) + + assertEquals(1250, clock.millis()) + } finally { + machine.close() + } + } + + fun testDiskWriteUsage() = runBlockingSimulation { + val interpreter = SimResourceInterpreter(coroutineContext, clock) + val machine = SimBareMetalMachine( + interpreter, + machineModel, + SimplePowerDriver(ConstantPowerModel(0.0)) + ) + + try { + machine.run(object : SimWorkload { + override fun onStart(ctx: SimMachineContext) { + val lifecycle = SimWorkloadLifecycle(ctx) + val disk = ctx.storage[0] + disk.write.startConsumer(lifecycle.waitFor(SimWorkConsumer(disk.write.capacity, utilization = 0.8))) + } + }) + + assertEquals(1250, clock.millis()) + } finally { + machine.close() + } + } + + @Test fun testCancellation() = runBlockingSimulation { val machine = SimBareMetalMachine( SimResourceInterpreter(coroutineContext, clock), |
