From f2028b23e25c8520f25a53771a1b261c4e991bb8 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 11 Jan 2021 15:37:34 +0100 Subject: Add hypervisor supporting space-shared VMs This change adds a new hypervisor implementation that supports virtual machine that have exclusive access to resources (e.g., CPU). --- .../opendc/compute/core/virt/driver/VirtDriver.kt | 8 +++++- .../org/opendc/compute/simulator/SimVirtDriver.kt | 31 +++++++++++++++++----- .../simulator/SimVirtProvisioningService.kt | 4 ++- 3 files changed, 34 insertions(+), 9 deletions(-) (limited to 'simulator/opendc-compute') diff --git a/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/VirtDriver.kt b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/VirtDriver.kt index 5ecfd357..68cc7b50 100644 --- a/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/VirtDriver.kt +++ b/simulator/opendc-compute/opendc-compute-core/src/main/kotlin/org/opendc/compute/core/virt/driver/VirtDriver.kt @@ -23,6 +23,7 @@ package org.opendc.compute.core.virt.driver import kotlinx.coroutines.flow.Flow +import org.opendc.compute.core.Flavor import org.opendc.compute.core.Server import org.opendc.compute.core.image.Image import org.opendc.compute.core.virt.HypervisorEvent @@ -39,6 +40,11 @@ public interface VirtDriver { */ public val events: Flow + /** + * Determine whether the specified [flavor] can still fit on this driver. + */ + public fun canFit(flavor: Flavor): Boolean + /** * Spawn the given [Image] on the compute resource of this driver. * @@ -50,7 +56,7 @@ public interface VirtDriver { public suspend fun spawn( name: String, image: Image, - flavor: org.opendc.compute.core.Flavor + flavor: Flavor ): Server public companion object Key : AbstractServiceKey(UUID.randomUUID(), "virtual-driver") diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt index f7eb9248..508720e2 100644 --- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtDriver.kt @@ -104,6 +104,14 @@ public class SimVirtDriver(private val coroutineScope: CoroutineScope) : VirtDri */ private val vms = HashSet() + override fun canFit(flavor: Flavor): Boolean { + val sufficientMemory = availableMemory > flavor.memorySize + val enoughCpus = ctx.machine.cpus.size >= flavor.cpuCount + val canFit = hypervisor.canFit(flavor.toMachineModel()) + + return sufficientMemory && enoughCpus && canFit + } + override suspend fun spawn(name: String, image: Image, flavor: Flavor): Server { val requiredMemory = flavor.memorySize if (availableMemory - requiredMemory < 0) { @@ -124,19 +132,26 @@ public class SimVirtDriver(private val coroutineScope: CoroutineScope) : VirtDri ) availableMemory -= requiredMemory - val originalCpu = ctx.machine.cpus[0] - val processingNode = originalCpu.node.copy(coreCount = flavor.cpuCount) - val processingUnits = (0 until flavor.cpuCount).map { originalCpu.copy(id = it, node = processingNode) } - val memoryUnits = listOf(MemoryUnit("Generic", "Generic", 3200.0, flavor.memorySize)) - val machine = SimMachineModel(processingUnits, memoryUnits) - val vm = VirtualMachine(server, events, hypervisor.createMachine(machine)) + val vm = VirtualMachine(server, events, hypervisor.createMachine(flavor.toMachineModel())) vms.add(vm) vmStarted(vm) eventFlow.emit(HypervisorEvent.VmsUpdated(this, vms.size, availableMemory)) return server } + /** + * Convert flavor to machine model. + */ + private fun Flavor.toMachineModel(): SimMachineModel { + val originalCpu = ctx.machine.cpus[0] + val processingNode = originalCpu.node.copy(coreCount = cpuCount) + val processingUnits = (0 until cpuCount).map { originalCpu.copy(id = it, node = processingNode) } + val memoryUnits = listOf(MemoryUnit("Generic", "Generic", 3200.0, memorySize)) + + return SimMachineModel(processingUnits, memoryUnits) + } + private fun vmStarted(vm: VirtualMachine) { vms.forEach { it -> vm.performanceInterferenceModel?.onStart(it.server.image.name) @@ -152,7 +167,7 @@ public class SimVirtDriver(private val coroutineScope: CoroutineScope) : VirtDri /** * A virtual machine instance that the driver manages. */ - private inner class VirtualMachine(server: Server, val events: EventFlow, machine: SimMachine) { + private inner class VirtualMachine(server: Server, val events: EventFlow, val machine: SimMachine) { val performanceInterferenceModel: PerformanceInterferenceModel? = server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel? val job = coroutineScope.launch { @@ -190,6 +205,8 @@ public class SimVirtDriver(private val coroutineScope: CoroutineScope) : VirtDri exit(null) } catch (cause: Throwable) { exit(cause) + } finally { + machine.close() } } diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt index f3a69f48..6b0021e1 100644 --- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimVirtProvisioningService.kt @@ -196,7 +196,9 @@ public class SimVirtProvisioningService( val requiredMemory = imageInstance.flavor.memorySize val selectedHv = allocationLogic.select(availableHypervisors, imageInstance) - if (selectedHv == null) { + if (selectedHv == null || !selectedHv.driver.canFit(imageInstance.flavor)) { + logger.debug { "Server ${imageInstance.server} selected for scheduling but no capacity available for it." } + if (requiredMemory > maxMemory || imageInstance.flavor.cpuCount > maxCores) { tracer.commit(VmSubmissionInvalidEvent(imageInstance.name)) -- cgit v1.2.3