diff options
68 files changed, 2853 insertions, 488 deletions
diff --git a/opendc-compute/opendc-compute-api/build.gradle.kts b/opendc-compute/opendc-compute-api/build.gradle.kts index f9b04299..2f855c79 100644 --- a/opendc-compute/opendc-compute-api/build.gradle.kts +++ b/opendc-compute/opendc-compute-api/build.gradle.kts @@ -26,3 +26,6 @@ description = "API interface for the OpenDC Compute service" plugins { `kotlin-library-conventions` } +dependencies { + implementation(project(mapOf("path" to ":opendc-simulator:opendc-simulator-compute"))) +} diff --git a/opendc-compute/opendc-compute-api/src/main/kotlin/org/opendc/compute/api/ComputeClient.kt b/opendc-compute/opendc-compute-api/src/main/kotlin/org/opendc/compute/api/ComputeClient.kt index 09cfe6f5..7863f20b 100644 --- a/opendc-compute/opendc-compute-api/src/main/kotlin/org/opendc/compute/api/ComputeClient.kt +++ b/opendc-compute/opendc-compute-api/src/main/kotlin/org/opendc/compute/api/ComputeClient.kt @@ -22,6 +22,7 @@ package org.opendc.compute.api +import org.opendc.simulator.compute.workload.SimWorkload import java.util.UUID /** @@ -113,6 +114,11 @@ public interface ComputeClient : AutoCloseable { start: Boolean = true, ): Server + public fun rescheduleServer( + server: Server, + workload: SimWorkload, + ) + /** * Release the resources associated with this client, preventing any further API calls. */ diff --git a/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt index 685a1fb3..b66aedf9 100644 --- a/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt +++ b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt @@ -22,11 +22,10 @@ package org.opendc.compute.carbon -import mu.KotlinLogging import org.opendc.trace.Trace import org.opendc.trace.conv.CARBON_INTENSITY_TIMESTAMP import org.opendc.trace.conv.CARBON_INTENSITY_VALUE -import org.opendc.trace.conv.TABLE_CARBON_INTENSITY +import org.opendc.trace.conv.TABLE_CARBON_INTENSITIES import java.io.File import java.lang.ref.SoftReference import java.time.Instant @@ -39,11 +38,6 @@ import java.util.concurrent.ConcurrentHashMap */ public class CarbonTraceLoader { /** - * The logger for this instance. - */ - private val logger = KotlinLogging.logger {} - - /** * The cache of workloads. */ private val cache = ConcurrentHashMap<String, SoftReference<List<CarbonFragment>>>() @@ -54,13 +48,11 @@ public class CarbonTraceLoader { * Read the metadata into a workload. */ private fun parseCarbon(trace: Trace): List<CarbonFragment> { - val reader = checkNotNull(trace.getTable(TABLE_CARBON_INTENSITY)).newReader() + val reader = checkNotNull(trace.getTable(TABLE_CARBON_INTENSITIES)).newReader() val startTimeCol = reader.resolve(CARBON_INTENSITY_TIMESTAMP) val carbonIntensityCol = reader.resolve(CARBON_INTENSITY_VALUE) - val entries = mutableListOf<CarbonFragment>() - try { while (reader.nextRow()) { val startTime = reader.getInstant(startTimeCol)!! diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/FailureModel.kt b/opendc-compute/opendc-compute-failure/build.gradle.kts index 9511017f..d6ec9116 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/FailureModel.kt +++ b/opendc-compute/opendc-compute-failure/build.gradle.kts @@ -20,24 +20,21 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.failure +description = "OpenDC Failure Service implementation" -import org.opendc.compute.service.ComputeService -import java.time.InstantSource -import java.util.random.RandomGenerator -import kotlin.coroutines.CoroutineContext +// Build configuration +plugins { + `kotlin-library-conventions` +} -/** - * Factory interface for constructing [HostFaultInjector] for modeling failures of compute service hosts. - */ -public interface FailureModel { - /** - * Construct a [HostFaultInjector] for the specified [service]. - */ - public fun createInjector( - context: CoroutineContext, - clock: InstantSource, - service: ComputeService, - random: RandomGenerator, - ): HostFaultInjector +dependencies { + api(projects.opendcCompute.opendcComputeApi) + implementation(projects.opendcCommon) + implementation(project(mapOf("path" to ":opendc-trace:opendc-trace-api"))) + implementation(project(mapOf("path" to ":opendc-simulator:opendc-simulator-compute"))) + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-service"))) + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-simulator"))) + + api(libs.commons.math3) + implementation(libs.kotlin.logging) } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/HostFault.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/hostfault/HostFault.kt index faf536ad..4134c58a 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/HostFault.kt +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/hostfault/HostFault.kt @@ -20,20 +20,22 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.failure +package org.opendc.compute.failure.hostfault +import org.opendc.compute.service.ComputeService import org.opendc.compute.simulator.SimHost -import java.time.InstantSource /** * Interface responsible for applying the fault to a host. */ -public interface HostFault { +public abstract class HostFault( + private val service: ComputeService, +) { /** * Apply the fault to the specified [victims]. */ - public suspend fun apply( - clock: InstantSource, + public abstract suspend fun apply( victims: List<SimHost>, + faultDuration: Long, ) } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/StartStopHostFault.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/hostfault/StartStopHostFault.kt index 45545f3b..85138025 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/StartStopHostFault.kt +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/hostfault/StartStopHostFault.kt @@ -20,39 +20,43 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.failure +package org.opendc.compute.failure.hostfault import kotlinx.coroutines.delay -import org.apache.commons.math3.distribution.RealDistribution +import org.opendc.compute.api.ComputeClient +import org.opendc.compute.service.ComputeService import org.opendc.compute.simulator.SimHost -import java.time.InstantSource -import kotlin.math.roundToLong +import org.opendc.simulator.compute.workload.SimWorkload /** - * A type of [HostFault] where the hosts are stopped and recover after some random amount of time. + * A type of [HostFault] where the hosts are stopped and recover after a given amount of time. */ -public class StartStopHostFault(private val duration: RealDistribution) : HostFault { +public class StartStopHostFault( + private val service: ComputeService, +) : HostFault(service) { override suspend fun apply( - clock: InstantSource, victims: List<SimHost>, + faultDuration: Long, ) { + val client: ComputeClient = service.newClient() + for (host in victims) { - host.fail() - } + val servers = host.instances - val df = (duration.sample() * 1000).roundToLong() // seconds to milliseconds + val snapshots = servers.map { (it.meta["workload"] as SimWorkload).snapshot() } + host.fail() - // Handle long overflow - if (clock.millis() + df <= 0) { - return + for ((server, snapshot) in servers.zip(snapshots)) { + client.rescheduleServer(server, snapshot) + } } - delay(df) + delay(faultDuration) for (host in victims) { host.recover() } } - override fun toString(): String = "StartStopHostFault[$duration]" + override fun toString(): String = "StartStopHostFault" } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/HostFaultInjectorImpl.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/FailureModel.kt index c75ce528..5f05d96c 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/HostFaultInjectorImpl.kt +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/FailureModel.kt @@ -20,44 +20,39 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.internal +package org.opendc.compute.failure.models import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.cancel -import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import org.apache.commons.math3.distribution.RealDistribution +import org.opendc.compute.failure.hostfault.HostFault +import org.opendc.compute.failure.hostfault.StartStopHostFault +import org.opendc.compute.failure.victimselector.StochasticVictimSelector +import org.opendc.compute.service.ComputeService import org.opendc.compute.simulator.SimHost -import org.opendc.compute.simulator.failure.HostFault -import org.opendc.compute.simulator.failure.HostFaultInjector -import org.opendc.compute.simulator.failure.VictimSelector import java.time.InstantSource +import java.util.random.RandomGenerator import kotlin.coroutines.CoroutineContext -import kotlin.math.roundToLong /** - * Internal implementation of the [HostFaultInjector] interface. - * - * @param context The scope to run the fault injector in. - * @param clock The [InstantSource] to keep track of simulation time. - * @param hosts The set of hosts to inject faults into. - * @param iat The inter-arrival time distribution of the failures (in hours). - * @param selector The [VictimSelector] to select the host victims. - * @param fault The type of [HostFault] to inject. + * Factory interface for constructing [FailureModel] for modeling failures of compute service hosts. */ -internal class HostFaultInjectorImpl( - private val context: CoroutineContext, - private val clock: InstantSource, - private val hosts: Set<SimHost>, - private val iat: RealDistribution, - private val selector: VictimSelector, - private val fault: HostFault, -) : HostFaultInjector { - /** - * The scope in which the injector runs. - */ - private val scope = CoroutineScope(context + Job()) +public abstract class FailureModel( + context: CoroutineContext, + protected val clock: InstantSource, + protected val service: ComputeService, + protected val random: RandomGenerator, +) : AutoCloseable { + protected val scope: CoroutineScope = CoroutineScope(context + Job()) + + // TODO: could at some point be extended to different types of faults + protected val fault: HostFault = StartStopHostFault(service) + + // TODO: could at some point be extended to different types of victim selectors + protected val victimSelector: StochasticVictimSelector = StochasticVictimSelector(random) + + protected val hosts: Set<SimHost> = service.hosts.map { it as SimHost }.toSet() /** * The [Job] that awaits the nearest fault in the system. @@ -67,7 +62,7 @@ internal class HostFaultInjectorImpl( /** * Start the fault injection into the system. */ - override fun start() { + public fun start() { if (job != null) { return } @@ -79,25 +74,7 @@ internal class HostFaultInjectorImpl( } } - /** - * Converge the injection process. - */ - private suspend fun runInjector() { - while (true) { - // Make sure to convert delay from hours to milliseconds - val d = (iat.sample() * 3.6e6).roundToLong() - - // Handle long overflow - if (clock.millis() + d <= 0) { - return - } - - delay(d) - - val victims = selector.select(hosts) - fault.apply(clock, victims) - } - } + public abstract suspend fun runInjector() /** * Stop the fault injector. diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/SampleBasedFailureModel.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/SampleBasedFailureModel.kt new file mode 100644 index 00000000..3ae66f6f --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/SampleBasedFailureModel.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 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.compute.failure.models + +import kotlinx.coroutines.delay +import org.apache.commons.math3.distribution.RealDistribution +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToLong + +/** + * Sample based failure model + * + * @property context + * @property clock + * @property service + * @property random + * @property iatSampler A distribution from which the time until the next fault is sampled in ms + * @property durationSampler A distribution from which the duration of a fault is sampled in s + * @property nohSampler A distribution from which the number of hosts that fault is sampled. + */ +public class SampleBasedFailureModel( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, + private val iatSampler: RealDistribution, + private val durationSampler: RealDistribution, + private val nohSampler: RealDistribution, +) : FailureModel(context, clock, service, random) { + override suspend fun runInjector() { + while (true) { + val iatSample = max(0.0, iatSampler.sample()) + val intervalDuration = (iatSample * 3.6e6).roundToLong() + + // Handle long overflow + if (clock.millis() + intervalDuration <= 0) { + return + } + + delay(intervalDuration) + + val numberOfHosts = min(1.0, max(0.0, nohSampler.sample())) + val victims = victimSelector.select(hosts, numberOfHosts) + + val durationSample = max(0.0, durationSampler.sample()) + val faultDuration = (durationSample * 3.6e6).toLong() + fault.apply(victims, faultDuration) + + break + } + } +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/TraceBasedFailureModel.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/TraceBasedFailureModel.kt new file mode 100644 index 00000000..db8bb1ec --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/TraceBasedFailureModel.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2024 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.compute.failure.models + +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.opendc.compute.service.ComputeService +import org.opendc.trace.Trace +import org.opendc.trace.conv.FAILURE_DURATION +import org.opendc.trace.conv.FAILURE_INTENSITY +import org.opendc.trace.conv.FAILURE_INTERVAL +import org.opendc.trace.conv.TABLE_FAILURES +import java.io.File +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * A definition of a Failure + * + * @property failureInterval The time between this and the previous failure in ms + * @property failureDuration The Duration of the failure in ms + * @property failureIntensity The ratio of hosts affected by the failure + * @constructor Create empty Failure + */ +public data class Failure( + val failureInterval: Long, + val failureDuration: Long, + val failureIntensity: Double, +) { + init { + require(failureInterval >= 0.0) { "A failure cannot start at a negative time" } + require(failureDuration >= 0.0) { "A failure can not have a duration of 0 or less" } + require(failureIntensity > 0.0 && failureIntensity <= 1.0) { "The intensity of a failure has to be in the range (0.0, 1.0]" } + } +} + +/** + * A [FailureModel] based on a provided parquet file + * The file provides a list of [Failure] objects + * + * + * @param context + * @param clock + * @param service + * @param random + * @param pathToTrace The path to the parquet file as a [String] + */ +public class TraceBasedFailureModel( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, + pathToTrace: String, + private val repeat: Boolean = false, +) : FailureModel(context, clock, service, random) { + private val failureList = loadTrace(pathToTrace) + + override suspend fun runInjector() { + do { + for (failure in failureList) { + delay(failure.failureInterval - clock.millis()) + + val victims = victimSelector.select(hosts, failure.failureIntensity) + scope.launch { + fault.apply(victims, failure.failureDuration) + } + } + } while (repeat) + } + + /** + * Load a list [Failure] objects from the provided [pathToFile] + * + * @param pathToFile + */ + private fun loadTrace(pathToFile: String): List<Failure> { + val trace = Trace.open(File(pathToFile), "failure") + + val reader = checkNotNull(trace.getTable(TABLE_FAILURES)).newReader() + + val failureStartTimeCol = reader.resolve(FAILURE_INTERVAL) + val failureDurationCol = reader.resolve(FAILURE_DURATION) + val failureIntensityCol = reader.resolve(FAILURE_INTENSITY) + + val entries = mutableListOf<Failure>() + + try { + while (reader.nextRow()) { + val failureStartTime = reader.getLong(failureStartTimeCol) + val failureDuration = reader.getLong(failureDurationCol) + val failureIntensity = reader.getDouble(failureIntensityCol) + + entries.add(Failure(failureStartTime, failureDuration, failureIntensity)) + } + + return entries + } catch (e: Exception) { + e.printStackTrace() + throw e + } finally { + reader.close() + } + } +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/G5k06.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/G5k06.kt new file mode 100644 index 00000000..da58250d --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/G5k06.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createG5k06Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 32.41), + ExponentialDistribution(rng, 7.41), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createG5k06Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.48, 14.37), + WeibullDistribution(rng, 0.35, 0.47), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createG5k06LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 1.51, 2.42), + LogNormalDistribution(rng, -2.0, 2.2), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createG5k06Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.34, 94.35), + GammaDistribution(rng, 0.19, 39.92), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Lanl05.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Lanl05.kt new file mode 100644 index 00000000..3e722630 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Lanl05.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createLanl05Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 1779.99), + ExponentialDistribution(rng, 5.92), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createLanl05Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.48, 816.60), + WeibullDistribution(rng, 0.58, 2.18), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createLanl05LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 5.56, 2.39), + LogNormalDistribution(rng, 0.05, 1.42), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createLanl05Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.35, 5102.71), + GammaDistribution(rng, 0.38, 15.44), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Ldns04.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Ldns04.kt new file mode 100644 index 00000000..4a8b3c0f --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Ldns04.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createLdns04Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 141.06), + ExponentialDistribution(rng, 8.61), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createLdns04Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.51, 79.30), + WeibullDistribution(rng, 0.63, 5.62), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createLdns04LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 3.25, 2.33), + LogNormalDistribution(rng, 0.91, 1.64), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createLdns04Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.39, 362.43), + GammaDistribution(rng, 0.51, 16.87), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Microsoft99.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Microsoft99.kt new file mode 100644 index 00000000..725f6622 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Microsoft99.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createMicrosoft99Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 67.01), + ExponentialDistribution(rng, 16.49), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createMicrosoft99Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.55, 35.30), + WeibullDistribution(rng, 0.60, 9.34), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createMicrosoft99LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 2.62, 1.84), + LogNormalDistribution(rng, 1.42, 1.54), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createMicrosoft99Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.41, 162.19), + GammaDistribution(rng, 0.46, 35.52), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Nd07cpu.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Nd07cpu.kt new file mode 100644 index 00000000..100a3a8d --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Nd07cpu.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createNd07cpuExp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 13.73), + ExponentialDistribution(rng, 4.25), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createNd07cpuWbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.45, 4.16), + WeibullDistribution(rng, 0.51, 0.74), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createNd07cpuLogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 0.30, 2.20), + LogNormalDistribution(rng, -1.02, 1.27), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createNd07cpuGam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.30, 46.16), + GammaDistribution(rng, 0.28, 15.07), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Overnet03.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Overnet03.kt new file mode 100644 index 00000000..4f5e3f84 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Overnet03.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createOvernet03Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 2.29), + ExponentialDistribution(rng, 12.00), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createOvernet03Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.85, 2.04), + WeibullDistribution(rng, 0.44, 2.98), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createOvernet03LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 0.19, 0.98), + LogNormalDistribution(rng, 0.08, 1.80), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createOvernet03Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.91, 2.53), + GammaDistribution(rng, 0.29, 41.64), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Pl05.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Pl05.kt new file mode 100644 index 00000000..3e1f1b58 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Pl05.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createPl05Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 159.49), + ExponentialDistribution(rng, 49.61), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createPl05Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.33, 19.35), + WeibullDistribution(rng, 0.36, 5.59), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createPl05LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 1.44, 2.86), + LogNormalDistribution(rng, 0.40, 2.45), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createPl05Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.20, 788.03), + GammaDistribution(rng, 0.21, 237.65), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/PrefabFailureModelFactory.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/PrefabFailureModelFactory.kt new file mode 100644 index 00000000..477f3ac4 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/PrefabFailureModelFactory.kt @@ -0,0 +1,140 @@ +/* + * 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. + */ + +@file:JvmName("FailureModels") + +package org.opendc.compute.failure.prefab + +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +public enum class FailurePrefab { + G5k06Exp, + G5k06Wbl, + G5k06LogN, + G5k06Gam, + Lanl05Exp, + Lanl05Wbl, + Lanl05LogN, + Lanl05Gam, + Ldns04Exp, + Ldns04Wbl, + Ldns04LogN, + Ldns04Gam, + Microsoft99Exp, + Microsoft99Wbl, + Microsoft99LogN, + Microsoft99Gam, + Nd07cpuExp, + Nd07cpuWbl, + Nd07cpuLogN, + Nd07cpuGam, + Overnet03Exp, + Overnet03Wbl, + Overnet03LogN, + Overnet03Gam, + Pl05Exp, + Pl05Wbl, + Pl05LogN, + Pl05Gam, + Skype06Exp, + Skype06Wbl, + Skype06LogN, + Skype06Gam, + Websites02Exp, + Websites02Wbl, + Websites02LogN, + Websites02Gam, +} + +/** + * Get a [SampleBasedFailureModel] based on the provided prefab. + * All Failure models are based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + * + * + * @param context + * @param clock + * @param service + * @param random + * @param prefab The name of the failure model prefab + * @return + */ +public fun createFailureModelPrefab( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, + prefab: FailurePrefab, +): SampleBasedFailureModel { + when (prefab) { + FailurePrefab.G5k06Exp -> return createG5k06Exp(context, clock, service, random) + FailurePrefab.G5k06Wbl -> return createG5k06Wbl(context, clock, service, random) + FailurePrefab.G5k06LogN -> return createG5k06LogN(context, clock, service, random) + FailurePrefab.G5k06Gam -> return createG5k06Gam(context, clock, service, random) + + FailurePrefab.Lanl05Exp -> return createLanl05Exp(context, clock, service, random) + FailurePrefab.Lanl05Wbl -> return createLanl05Wbl(context, clock, service, random) + FailurePrefab.Lanl05LogN -> return createLanl05LogN(context, clock, service, random) + FailurePrefab.Lanl05Gam -> return createLanl05Gam(context, clock, service, random) + + FailurePrefab.Ldns04Exp -> return createLdns04Exp(context, clock, service, random) + FailurePrefab.Ldns04Wbl -> return createLdns04Wbl(context, clock, service, random) + FailurePrefab.Ldns04LogN -> return createLdns04LogN(context, clock, service, random) + FailurePrefab.Ldns04Gam -> return createLdns04Gam(context, clock, service, random) + + FailurePrefab.Microsoft99Exp -> return createMicrosoft99Exp(context, clock, service, random) + FailurePrefab.Microsoft99Wbl -> return createMicrosoft99Wbl(context, clock, service, random) + FailurePrefab.Microsoft99LogN -> return createMicrosoft99LogN(context, clock, service, random) + FailurePrefab.Microsoft99Gam -> return createMicrosoft99Gam(context, clock, service, random) + + FailurePrefab.Nd07cpuExp -> return createNd07cpuExp(context, clock, service, random) + FailurePrefab.Nd07cpuWbl -> return createNd07cpuWbl(context, clock, service, random) + FailurePrefab.Nd07cpuLogN -> return createNd07cpuLogN(context, clock, service, random) + FailurePrefab.Nd07cpuGam -> return createNd07cpuGam(context, clock, service, random) + + FailurePrefab.Overnet03Exp -> return createOvernet03Exp(context, clock, service, random) + FailurePrefab.Overnet03Wbl -> return createOvernet03Wbl(context, clock, service, random) + FailurePrefab.Overnet03LogN -> return createOvernet03LogN(context, clock, service, random) + FailurePrefab.Overnet03Gam -> return createOvernet03Gam(context, clock, service, random) + + FailurePrefab.Pl05Exp -> return createPl05Exp(context, clock, service, random) + FailurePrefab.Pl05Wbl -> return createPl05Wbl(context, clock, service, random) + FailurePrefab.Pl05LogN -> return createPl05LogN(context, clock, service, random) + FailurePrefab.Pl05Gam -> return createPl05Gam(context, clock, service, random) + + FailurePrefab.Skype06Exp -> return createSkype06Exp(context, clock, service, random) + FailurePrefab.Skype06Wbl -> return createSkype06Wbl(context, clock, service, random) + FailurePrefab.Skype06LogN -> return createSkype06LogN(context, clock, service, random) + FailurePrefab.Skype06Gam -> return createSkype06Gam(context, clock, service, random) + + FailurePrefab.Websites02Exp -> return createWebsites02Exp(context, clock, service, random) + FailurePrefab.Websites02Wbl -> return createWebsites02Wbl(context, clock, service, random) + FailurePrefab.Websites02LogN -> return createWebsites02LogN(context, clock, service, random) + FailurePrefab.Websites02Gam -> return createWebsites02Gam(context, clock, service, random) + + else -> error("Unknown failure prefab: $prefab") + } +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Skype06.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Skype06.kt new file mode 100644 index 00000000..7495bf66 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Skype06.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createSkype06Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 16.27), + ExponentialDistribution(rng, 14.31), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createSkype06Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.64, 10.86), + WeibullDistribution(rng, 0.63, 9.48), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createSkype06LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 1.60, 1.57), + LogNormalDistribution(rng, 1.40, 1.73), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createSkype06Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.53, 30.79), + GammaDistribution(rng, 0.50, 28.53), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Websites02.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Websites02.kt new file mode 100644 index 00000000..77bb0d64 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Websites02.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 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.compute.failure.prefab + +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.service.ComputeService +import java.time.InstantSource +import java.util.random.RandomGenerator +import kotlin.coroutines.CoroutineContext + +/** + * Failure models based on values taken from "The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems" + * Which can be found at https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634 + */ +public fun createWebsites02Exp( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + ExponentialDistribution(rng, 11.85), + ExponentialDistribution(rng, 1.18), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createWebsites02Wbl( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + WeibullDistribution(rng, 0.46, 3.68), + WeibullDistribution(rng, 0.65, 0.61), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createWebsites02LogN( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + LogNormalDistribution(rng, 0.23, 2.02), + LogNormalDistribution(rng, -1.12, 1.13), + UniformRealDistribution(0.0, 1.0), + ) +} + +public fun createWebsites02Gam( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: RandomGenerator, +): SampleBasedFailureModel { + val rng = Well19937c(random.nextLong()) + + return SampleBasedFailureModel( + context, + clock, + service, + random, + GammaDistribution(rng, 0.31, 38.67), + GammaDistribution(rng, 0.50, 2.37), + UniformRealDistribution(0.0, 1.0), + ) +} diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/StochasticVictimSelector.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/victimselector/StochasticVictimSelector.kt index 93463cdb..fef60eb3 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/StochasticVictimSelector.kt +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/victimselector/StochasticVictimSelector.kt @@ -20,28 +20,32 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.failure +package org.opendc.compute.failure.victimselector -import org.apache.commons.math3.distribution.RealDistribution import org.opendc.compute.simulator.SimHost -import java.util.ArrayList import java.util.SplittableRandom import java.util.random.RandomGenerator -import kotlin.math.roundToInt +import kotlin.math.max +import kotlin.math.min /** * A [VictimSelector] that stochastically selects a set of hosts to be failed. */ public class StochasticVictimSelector( - private val size: RealDistribution, private val random: RandomGenerator = SplittableRandom(0), ) : VictimSelector { - override fun select(hosts: Set<SimHost>): List<SimHost> { - val n = size.sample().roundToInt() - val result = ArrayList<SimHost>(n) + override fun select(numberOfHosts: Int): List<SimHost> { + error("select with only int cannot be used in this type of VictimSelector") + } + + override fun select( + hosts: Set<SimHost>, + numberOfHosts: Int, + ): List<SimHost> { + val result = ArrayList<SimHost>(numberOfHosts) val random = random - var samplesNeeded = n + var samplesNeeded = numberOfHosts var remainingHosts = hosts.size val iterator = hosts.iterator() @@ -59,5 +63,20 @@ public class StochasticVictimSelector( return result } - override fun toString(): String = "StochasticVictimSelector[$size]" + override fun select(failureIntensity: Double): List<SimHost> { + error("select with only int cannot be used in this type of VictimSelector") + } + + override fun select( + hosts: Set<SimHost>, + failureIntensity: Double, + ): List<SimHost> { + // clamp value between 0.0 and 1.0 + val intensity = min(1.0, max(0.0, failureIntensity)) + val numberOfHosts = (hosts.size * intensity).toInt() + + return hosts.asSequence().shuffled().take(numberOfHosts).toList() + } + + override fun toString(): String = "StochasticVictimSelector" } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/VictimSelector.kt b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/victimselector/VictimSelector.kt index b5610284..955cbced 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/VictimSelector.kt +++ b/opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/victimselector/VictimSelector.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.failure +package org.opendc.compute.failure.victimselector import org.opendc.compute.simulator.SimHost @@ -31,5 +31,17 @@ public interface VictimSelector { /** * Select the hosts from [hosts] where a fault will be injected. */ - public fun select(hosts: Set<SimHost>): List<SimHost> + public fun select( + hosts: Set<SimHost>, + numberOfHosts: Int, + ): List<SimHost> + + public fun select(numberOfHosts: Int): List<SimHost> + + public fun select(failureIntensity: Double): List<SimHost> + + public fun select( + hosts: Set<SimHost>, + failureIntensity: Double, + ): List<SimHost> } diff --git a/opendc-compute/opendc-compute-failure/src/test/resources/log4j2.xml b/opendc-compute/opendc-compute-failure/src/test/resources/log4j2.xml new file mode 100644 index 00000000..0dfb75f2 --- /dev/null +++ b/opendc-compute/opendc-compute-failure/src/test/resources/log4j2.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> + +<Configuration status="WARN" packages="org.apache.logging.log4j.core"> + <Appenders> + <Console name="Console" target="SYSTEM_OUT"> + <PatternLayout pattern="%d{HH:mm:ss.SSS} [%highlight{%-5level}] %logger{36} - %msg%n" disableAnsi="false"/> + </Console> + </Appenders> + <Loggers> + <Logger name="org.opendc" level="trace" additivity="false"> + <AppenderRef ref="Console"/> + </Logger> + <Root level="info"> + <AppenderRef ref="Console"/> + </Root> + </Loggers> +</Configuration> diff --git a/opendc-compute/opendc-compute-service/build.gradle.kts b/opendc-compute/opendc-compute-service/build.gradle.kts index 0efdb05f..cd25e05c 100644 --- a/opendc-compute/opendc-compute-service/build.gradle.kts +++ b/opendc-compute/opendc-compute-service/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { api(projects.opendcCompute.opendcComputeApi) implementation(projects.opendcCommon) implementation(libs.kotlin.logging) + implementation(project(mapOf("path" to ":opendc-simulator:opendc-simulator-compute"))) testImplementation(projects.opendcSimulator.opendcSimulatorCore) testImplementation(libs.log4j.slf4j) diff --git a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ComputeService.java b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ComputeService.java index 167b13c7..a7e9f509 100644 --- a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ComputeService.java +++ b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ComputeService.java @@ -52,6 +52,7 @@ import org.opendc.compute.service.driver.HostModel; import org.opendc.compute.service.driver.HostState; import org.opendc.compute.service.scheduler.ComputeScheduler; import org.opendc.compute.service.telemetry.SchedulerStats; +import org.opendc.simulator.compute.workload.SimWorkload; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -161,7 +162,9 @@ public final class ComputeService implements AutoCloseable { serviceServer.setState(newState); - if (newState == ServerState.TERMINATED || newState == ServerState.DELETED) { + if (newState == ServerState.TERMINATED + || newState == ServerState.DELETED + || newState == ServerState.ERROR) { LOGGER.info("Server {} {} {} finished", server.getUid(), server.getName(), server.getFlavor()); if (activeServers.remove(server) != null) { @@ -353,6 +356,8 @@ public final class ComputeService implements AutoCloseable { * Run a single scheduling iteration. */ private void doSchedule() { + // reorder tasks + while (!queue.isEmpty()) { SchedulingRequest request = queue.peek(); @@ -363,6 +368,9 @@ public final class ComputeService implements AutoCloseable { } final ServiceServer server = request.server; + // Check if all dependencies are met + // otherwise continue + final ServiceFlavor flavor = server.getFlavor(); final HostView hv = scheduler.select(request.server); @@ -582,6 +590,20 @@ public final class ComputeService implements AutoCloseable { public String toString() { return "ComputeService.Client"; } + + @Nullable + @Override + public void rescheduleServer(@NotNull Server server, @NotNull SimWorkload workload) { + ServiceServer internalServer = (ServiceServer) findServer(server.getUid()); + Host from = service.lookupHost(internalServer); + + from.delete(internalServer); + + internalServer.host = null; + + internalServer.setWorkload(workload); + internalServer.start(); + } } /** diff --git a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ServiceServer.java b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ServiceServer.java index 265feac0..e363faf2 100644 --- a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ServiceServer.java +++ b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ServiceServer.java @@ -25,6 +25,7 @@ package org.opendc.compute.service; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -46,11 +47,12 @@ public final class ServiceServer implements Server { private final ComputeService service; private final UUID uid; + private final String name; private final ServiceFlavor flavor; private final ServiceImage image; private final Map<String, String> labels; - private final Map<String, ?> meta; + private Map<String, ?> meta; private final List<ServerWatcher> watchers = new ArrayList<>(); private ServerState state = ServerState.TERMINATED; @@ -111,6 +113,13 @@ public final class ServiceServer implements Server { return Collections.unmodifiableMap(meta); } + public void setWorkload(Object _workload) { + Map<String, Object> new_meta = new HashMap<String, Object>(); + new_meta.put("workload", _workload); + + meta = new_meta; + } + @NotNull @Override public ServerState getState() { diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/FilterScheduler.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/FilterScheduler.kt index cdcd1af0..41118386 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/FilterScheduler.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/FilterScheduler.kt @@ -101,6 +101,7 @@ public class FilterScheduler( filteredHosts } + // fixme: currently finding no matching hosts can result in an error return when (val maxSize = min(subsetSize, subset.size)) { 0 -> null 1 -> subset[0] diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/ComputeFilter.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/ComputeFilter.kt index 23590c13..dd707f60 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/ComputeFilter.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/ComputeFilter.kt @@ -34,7 +34,8 @@ public class ComputeFilter : HostFilter { host: HostView, server: Server, ): Boolean { - return host.host.state == HostState.UP + val result = host.host.state == HostState.UP + return result } override fun toString(): String = "ComputeFilter" diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/RamFilter.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/RamFilter.kt index 4792a7a0..d8c3d540 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/RamFilter.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/RamFilter.kt @@ -35,19 +35,21 @@ public class RamFilter(private val allocationRatio: Double) : HostFilter { host: HostView, server: Server, ): Boolean { - val requested = server.flavor.memorySize - val available = host.availableMemory - val total = host.host.model.memoryCapacity + val requestedMemory = server.flavor.memorySize + val availableMemory = host.availableMemory + val memoryCapacity = host.host.model.memoryCapacity // Do not allow an instance to overcommit against itself, only against // other instances. - if (requested > total) { + if (requestedMemory > memoryCapacity) { return false } - val limit = total * allocationRatio - val used = total - available + val limit = memoryCapacity * allocationRatio + val used = memoryCapacity - availableMemory val usable = limit - used - return usable >= requested + + val result = usable >= requestedMemory + return result } } diff --git a/opendc-compute/opendc-compute-simulator/build.gradle.kts b/opendc-compute/opendc-compute-simulator/build.gradle.kts index 0cddd296..20ceb93e 100644 --- a/opendc-compute/opendc-compute-simulator/build.gradle.kts +++ b/opendc-compute/opendc-compute-simulator/build.gradle.kts @@ -39,6 +39,8 @@ dependencies { implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-telemetry"))) implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-carbon"))) + implementation(project(mapOf("path" to ":opendc-trace:opendc-trace-api"))) + testImplementation(projects.opendcSimulator.opendcSimulatorCore) testRuntimeOnly(libs.slf4j.simple) } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt index 84799123..00f2acb3 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt @@ -190,6 +190,9 @@ public class SimHost( override fun delete(server: Server) { val guest = guests[server] ?: return guest.delete() + + guests.remove(server) + localGuests.remove(guest) } override fun addListener(listener: HostListener) { diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/FailureModelFactory.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/checkpoints/CheckpointModel.kt index 406665c7..781c2025 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/FailureModelFactory.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/checkpoints/CheckpointModel.kt @@ -20,22 +20,9 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.failure +package org.opendc.compute.simulator.checkpoints -import org.opendc.compute.simulator.failure.models.Grid5000 -import java.time.Duration -import kotlin.math.roundToLong - -/** - * Get failure model - * - * @param failureInterval The interval of failures occurring in s - * @return - */ -public fun getFailureModel(failureInterval: Double): FailureModel? { - return if (failureInterval > 0) { - Grid5000(Duration.ofSeconds(failureInterval.roundToLong())) - } else { - null - } -} +public data class CheckpointModel( + val checkpointWait: Long = 60 * 60 * 1000, + val checkpointTime: Long = 5 * 60 * 1000, +) diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/HostFaultInjector.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/HostFaultInjector.kt deleted file mode 100644 index 26084a1b..00000000 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/HostFaultInjector.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 org.opendc.compute.simulator.failure - -import org.apache.commons.math3.distribution.RealDistribution -import org.opendc.compute.simulator.SimHost -import org.opendc.compute.simulator.internal.HostFaultInjectorImpl -import java.time.Clock -import java.time.InstantSource -import kotlin.coroutines.CoroutineContext - -/** - * An interface for stochastically injecting faults into a set of hosts. - */ -public interface HostFaultInjector : AutoCloseable { - /** - * Start fault injection. - */ - public fun start() - - /** - * Stop fault injection into the system. - */ - public override fun close() - - public companion object { - /** - * Construct a new [HostFaultInjector]. - * - * @param context The scope to run the fault injector in. - * @param clock The [Clock] to keep track of simulation time. - * @param hosts The hosts to inject the faults into. - * @param iat The inter-arrival time distribution of the failures (in hours). - * @param selector The [VictimSelector] to select the host victims. - * @param fault The type of [HostFault] to inject. - */ - public operator fun invoke( - context: CoroutineContext, - clock: InstantSource, - hosts: Set<SimHost>, - iat: RealDistribution, - selector: VictimSelector, - fault: HostFault, - ): HostFaultInjector = HostFaultInjectorImpl(context, clock, hosts, iat, selector, fault) - } -} diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/models/Grid5000.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/models/Grid5000.kt deleted file mode 100644 index 8aacc49d..00000000 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/models/Grid5000.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -@file:JvmName("FailureModels") - -package org.opendc.compute.simulator.failure.models - -import org.apache.commons.math3.distribution.LogNormalDistribution -import org.apache.commons.math3.random.Well19937c -import org.opendc.compute.service.ComputeService -import org.opendc.compute.simulator.SimHost -import org.opendc.compute.simulator.failure.FailureModel -import org.opendc.compute.simulator.failure.HostFaultInjector -import org.opendc.compute.simulator.failure.StartStopHostFault -import org.opendc.compute.simulator.failure.StochasticVictimSelector -import java.time.Duration -import java.time.InstantSource -import java.util.random.RandomGenerator -import kotlin.coroutines.CoroutineContext -import kotlin.math.ln - -/** - * A [FailureModel] based on the GRID'5000 failure trace. - * - * This fault injector uses parameters from the GRID'5000 failure trace as described in - * "A Framework for the Study of Grid Inter-Operation Mechanisms", A. Iosup, 2009. - */ -public class Grid5000(private val failureInterval: Duration) : FailureModel { - override fun createInjector( - context: CoroutineContext, - clock: InstantSource, - service: ComputeService, - random: RandomGenerator, - ): HostFaultInjector { - val rng = Well19937c(random.nextLong()) - val hosts = service.hosts.map { it as SimHost }.toSet() - - // Parameters from A. Iosup, A Framework for the Study of Grid Inter-Operation Mechanisms, 2009 - // GRID'5000 - return HostFaultInjector( - context, - clock, - hosts, - iat = LogNormalDistribution(rng, ln(failureInterval.toHours().toDouble()), 1.03), - selector = StochasticVictimSelector(LogNormalDistribution(rng, 1.88, 1.25), random), - fault = StartStopHostFault(LogNormalDistribution(rng, 8.89, 2.71)), - ) - } - - override fun toString(): String = "Grid5000FailureModel" -} diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt index c5293a8d..7d4b7302 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt @@ -38,7 +38,8 @@ internal object DefaultWorkloadMapper : SimWorkloadMapper { override fun createWorkload(server: Server): SimWorkload { val workload = delegate.createWorkload(server) - val bootWorkload = SimWorkloads.runtime(Duration.ofMillis(1), 0.8) + // FIXME: look at connecting this to frontend. Probably not needed since the duration is so small + val bootWorkload = SimWorkloads.runtime(Duration.ofMillis(1), 0.8, 0L, 0L) return SimWorkloads.chain(bootWorkload, workload) } } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt index e268c506..cbdda0cb 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt @@ -186,7 +186,11 @@ internal class Guest( private fun doStop(target: ServerState) { assert(ctx != null) { "Invalid job state" } val ctx = ctx ?: return - ctx.shutdown() + if (target == ServerState.ERROR) { + ctx.shutdown(Exception("Stopped because of ERROR")) + } else { + ctx.shutdown() + } state = target } diff --git a/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/failure/HostFaultInjectorTest.kt b/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/failure/HostFaultInjectorTest.kt deleted file mode 100644 index 690bf472..00000000 --- a/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/failure/HostFaultInjectorTest.kt +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.compute.simulator.failure - -import io.mockk.coVerify -import io.mockk.mockk -import kotlinx.coroutines.delay -import org.apache.commons.math3.distribution.LogNormalDistribution -import org.apache.commons.math3.random.Well19937c -import org.junit.jupiter.api.Test -import org.opendc.compute.simulator.SimHost -import org.opendc.simulator.kotlin.runSimulation -import java.time.Duration -import java.time.InstantSource -import kotlin.coroutines.CoroutineContext -import kotlin.math.ln - -/** - * Test suite for [HostFaultInjector] class. - */ -class HostFaultInjectorTest { - /** - * Simple test case to test that nothing happens when the injector is not started. - */ - @Test - fun testInjectorNotStarted() = - runSimulation { - val host = mockk<SimHost>(relaxUnitFun = true) - - val injector = createSimpleInjector(coroutineContext, timeSource, setOf(host)) - - coVerify(exactly = 0) { host.fail() } - coVerify(exactly = 0) { host.recover() } - - injector.close() - } - - /** - * Simple test case to test a start stop fault where the machine is stopped and started after some time. - */ - @Test - fun testInjectorStopsMachine() = - runSimulation { - val host = mockk<SimHost>(relaxUnitFun = true) - - val injector = createSimpleInjector(coroutineContext, timeSource, setOf(host)) - - injector.start() - - delay(Duration.ofDays(55).toMillis()) - - injector.close() - - coVerify(exactly = 1) { host.fail() } - coVerify(exactly = 1) { host.recover() } - } - - /** - * Simple test case to test a start stop fault where multiple machines are stopped. - */ - @Test - fun testInjectorStopsMultipleMachines() = - runSimulation { - val hosts = - listOf<SimHost>( - mockk(relaxUnitFun = true), - mockk(relaxUnitFun = true), - ) - - val injector = createSimpleInjector(coroutineContext, timeSource, hosts.toSet()) - - injector.start() - - delay(Duration.ofDays(55).toMillis()) - - injector.close() - - coVerify(exactly = 1) { hosts[0].fail() } - coVerify(exactly = 1) { hosts[1].fail() } - coVerify(exactly = 1) { hosts[0].recover() } - coVerify(exactly = 1) { hosts[1].recover() } - } - - /** - * Create a simple start stop fault injector. - */ - private fun createSimpleInjector( - context: CoroutineContext, - clock: InstantSource, - hosts: Set<SimHost>, - ): HostFaultInjector { - val rng = Well19937c(0) - val iat = LogNormalDistribution(rng, ln(24 * 7.0), 1.03) - val selector = StochasticVictimSelector(LogNormalDistribution(rng, 1.88, 1.25)) - val fault = StartStopHostFault(LogNormalDistribution(rng, 8.89, 2.71)) - - return HostFaultInjector(context, clock, hosts, iat, selector, fault) - } -} diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyReader.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyReader.kt index 63719c0a..f374b71f 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyReader.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyReader.kt @@ -28,17 +28,19 @@ import kotlinx.serialization.json.decodeFromStream import org.opendc.compute.topology.specs.TopologySpec import java.io.File import java.io.InputStream +import java.nio.file.Path +import kotlin.io.path.inputStream /** * A helper class for reading a topology specification file. */ public class TopologyReader { - @OptIn(ExperimentalSerializationApi::class) - public fun read(file: File): TopologySpec { - val input = file.inputStream() - val obj = Json.decodeFromStream<TopologySpec>(input) + public fun read(path: Path): TopologySpec { + return read(path.inputStream()) + } - return obj + public fun read(file: File): TopologySpec { + return read(file.inputStream()) } /** diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt index deb50f5c..7bea920e 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt @@ -51,4 +51,6 @@ public data class VirtualMachine( val stopTime: Instant, val trace: SimTrace, val interferenceProfile: VmInterferenceProfile?, -) +) { + val duration: Long = stopTime.toEpochMilli() - startTime.toEpochMilli() +} diff --git a/opendc-experiments/opendc-experiments-base/build.gradle.kts b/opendc-experiments/opendc-experiments-base/build.gradle.kts index c75af87b..30510785 100644 --- a/opendc-experiments/opendc-experiments-base/build.gradle.kts +++ b/opendc-experiments/opendc-experiments-base/build.gradle.kts @@ -37,11 +37,13 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") implementation(libs.progressbar) + implementation(project(mapOf("path" to ":opendc-simulator:opendc-simulator-core"))) + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-workload"))) implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-telemetry"))) - implementation(project(mapOf("path" to ":opendc-simulator:opendc-simulator-core"))) implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-topology"))) implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-carbon"))) + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-failure"))) runtimeOnly(libs.log4j.core) runtimeOnly(libs.log4j.slf4j) diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioHelpers.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioHelpers.kt index e1305b3f..970754b0 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioHelpers.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioHelpers.kt @@ -20,11 +20,11 @@ * SOFTWARE. */ -@file:JvmName("TraceHelpers") +@file:JvmName("ScenarioHelpers") package org.opendc.experiments.base.runner -import FailureModelSpec +import CheckpointModelSpec import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -33,9 +33,14 @@ import kotlinx.coroutines.yield import org.opendc.compute.api.Server import org.opendc.compute.api.ServerState import org.opendc.compute.api.ServerWatcher +import org.opendc.compute.failure.models.FailureModel import org.opendc.compute.service.ComputeService import org.opendc.compute.workload.VirtualMachine +import org.opendc.experiments.base.scenario.specs.FailureModelSpec +import org.opendc.experiments.base.scenario.specs.createFailureModel import java.time.InstantSource +import java.util.Random +import kotlin.coroutines.coroutineContext import kotlin.math.max /** @@ -45,7 +50,7 @@ import kotlin.math.max */ public class RunningServerWatcher : ServerWatcher { // TODO: make this changeable - private val unlockStates: List<ServerState> = listOf(ServerState.TERMINATED, ServerState.ERROR, ServerState.DELETED) + private val unlockStates: List<ServerState> = listOf(ServerState.DELETED, ServerState.TERMINATED) private val mutex: Mutex = Mutex() @@ -80,18 +85,25 @@ public suspend fun ComputeService.replay( clock: InstantSource, trace: List<VirtualMachine>, failureModelSpec: FailureModelSpec? = null, + checkpointModelSpec: CheckpointModelSpec? = null, seed: Long = 0, submitImmediately: Boolean = false, ) { - // TODO: add failureModel functionality val client = newClient() + // Create a failure model based on the failureModelSpec, if not null, otherwise set failureModel to null + val failureModel: FailureModel? = + failureModelSpec?.let { + createFailureModel(coroutineContext, clock, this, Random(seed), it) + } + // Create new image for the virtual machine val image = client.newImage("vm-image") try { coroutineScope { - // TODO: start failure model when implemented + // Start the fault injector + failureModel?.start() var simulationOffset = Long.MIN_VALUE @@ -109,7 +121,17 @@ public suspend fun ComputeService.replay( delay(max(0, (start - now - simulationOffset))) } - val workload = entry.trace.createWorkload(start) + val checkpointTime = checkpointModelSpec?.checkpointTime ?: 0L + val checkpointWait = checkpointModelSpec?.checkpointWait ?: 0L + +// val workload = SimRuntimeWorkload( +// entry.duration, +// 1.0, +// checkpointTime, +// checkpointWait +// ) + + val workload = entry.trace.createWorkload(start, checkpointTime, checkpointWait) val meta = mutableMapOf<String, Any>("workload" to workload) launch { @@ -140,7 +162,7 @@ public suspend fun ComputeService.replay( } yield() } finally { - // TODO: close failure model when implemented + failureModel?.close() client.close() } } diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt index d6ee5d72..cb4fdd46 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt @@ -116,7 +116,7 @@ public fun runScenario( val serviceDomain = "compute.opendc.org" Provisioner(dispatcher, seed).use { provisioner -> - val topology = clusterTopology(scenario.topology.pathToFile, Random(seed)) + val topology = clusterTopology(scenario.topologySpec.pathToFile, Random(seed)) provisioner.runSteps( setupComputeService( serviceDomain, @@ -125,15 +125,15 @@ public fun runScenario( setupHosts(serviceDomain, topology, optimize = true), ) - val workloadLoader = ComputeWorkloadLoader(File(scenario.workload.pathToFile)) - val vms = getWorkloadType(scenario.workload.type).resolve(workloadLoader, Random(seed)) + val workloadLoader = ComputeWorkloadLoader(File(scenario.workloadSpec.pathToFile)) + val vms = getWorkloadType(scenario.workloadSpec.type).resolve(workloadLoader, Random(seed)) val carbonTrace = getCarbonTrace(scenario.carbonTracePath) val startTime = Duration.ofMillis(vms.minOf { it.startTime }.toEpochMilli()) addExportModel(provisioner, serviceDomain, scenario, seed, startTime, carbonTrace, index) val service = provisioner.registry.resolve(serviceDomain, ComputeService::class.java)!! - service.replay(timeSource, vms, failureModelSpec = scenario.failureModel, seed = seed) + service.replay(timeSource, vms, failureModelSpec = scenario.failureModelSpec, seed = seed) } } @@ -164,7 +164,7 @@ public fun addExportModel( "seed=$seed", bufferSize = 4096, ), - Duration.ofSeconds(scenario.exportModel.exportInterval), + Duration.ofSeconds(scenario.exportModelSpec.exportInterval), startTime, carbonTrace, ), @@ -184,10 +184,10 @@ public fun clearOutputFolder(outputFolderPath: String) { * @param folderPath The path to the output folder */ private fun setupOutputFolderStructure(folderPath: String) { - val trackrPath = folderPath + "/trackr.json" - val simulationAnalysisPath = folderPath + "/simulation-analysis/" - val energyAnalysisPath = simulationAnalysisPath + "/power_draw/" - val emissionsAnalysisPath = simulationAnalysisPath + "/carbon_emission/" + val trackrPath = "$folderPath/trackr.json" + val simulationAnalysisPath = "$folderPath/simulation-analysis/" + val energyAnalysisPath = "$simulationAnalysisPath/power_draw/" + val emissionsAnalysisPath = "$simulationAnalysisPath/carbon_emission/" File(folderPath).mkdir() File(trackrPath).createNewFile() diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/Scenario.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/Scenario.kt index 7f0308fc..02a8234d 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/Scenario.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/Scenario.kt @@ -23,10 +23,11 @@ package org.opendc.experiments.base.scenario import AllocationPolicySpec +import CheckpointModelSpec import ExportModelSpec -import FailureModelSpec import ScenarioTopologySpec import WorkloadSpec +import org.opendc.experiments.base.scenario.specs.FailureModelSpec /** * A data class representing a scenario for a set of experiments. @@ -41,15 +42,15 @@ import WorkloadSpec * @property runs The Int representing the number of runs of the scenario. It defaults to 1. * @property initialSeed The Int representing the initial seed of the scenario. It defaults to 0. */ - public data class Scenario( var id: Int = -1, - val topology: ScenarioTopologySpec, - val workload: WorkloadSpec, - val allocationPolicy: AllocationPolicySpec, - val failureModel: FailureModelSpec?, + val topologySpec: ScenarioTopologySpec, + val workloadSpec: WorkloadSpec, + val allocationPolicySpec: AllocationPolicySpec, + val failureModelSpec: FailureModelSpec?, + val checkpointModelSpec: CheckpointModelSpec?, val carbonTracePath: String? = null, - val exportModel: ExportModelSpec = ExportModelSpec(), + val exportModelSpec: ExportModelSpec = ExportModelSpec(), val outputFolder: String = "output", val name: String = "", val runs: Int = 1, diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioFactories.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioFactories.kt index 19f8ebf0..e7b52c55 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioFactories.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioFactories.kt @@ -22,7 +22,6 @@ package org.opendc.experiments.base.scenario -import ScenarioTopologySpec import org.opendc.experiments.base.scenario.specs.ScenarioSpec import java.io.File @@ -60,35 +59,36 @@ public fun getScenarios(scenarioSpec: ScenarioSpec): List<Scenario> { val outputFolder = scenarioSpec.outputFolder + "/" + scenarioSpec.name File(outputFolder).mkdirs() - val trackrPath = outputFolder + "/trackr.json" + val trackrPath = "$outputFolder/trackr.json" File(trackrPath).createNewFile() val scenarios = mutableListOf<Scenario>() - var scenarioID = 0 - for (scenarioTopologySpec in scenarioSpec.topologies) { + for ((scenarioID, scenarioTopologySpec) in scenarioSpec.topologies.withIndex()) { for (workloadSpec in scenarioSpec.workloads) { for (allocationPolicySpec in scenarioSpec.allocationPolicies) { for (failureModelSpec in scenarioSpec.failureModels) { - for (carbonTracePath in scenarioSpec.carbonTracePaths) { - for (exportModelSpec in scenarioSpec.exportModels) { - val scenario = - Scenario( - id = scenarioID, - topology = scenarioTopologySpec, - workload = workloadSpec, - allocationPolicy = allocationPolicySpec, - failureModel = failureModelSpec, - carbonTracePath = carbonTracePath, - exportModel = exportModelSpec, - outputFolder = outputFolder, - name = scenarioID.toString(), - runs = scenarioSpec.runs, - initialSeed = scenarioSpec.initialSeed, - ) - trackScenario(scenarioSpec, outputFolder, scenario, scenarioTopologySpec) - scenarios.add(scenario) - scenarioID++ + for (checkpointModelSpec in scenarioSpec.checkpointModels) { + for (carbonTracePath in scenarioSpec.carbonTracePaths) { + for (exportModelSpec in scenarioSpec.exportModels) { + val scenario = + Scenario( + id = scenarioID, + topologySpec = scenarioTopologySpec, + workloadSpec = workloadSpec, + allocationPolicySpec = allocationPolicySpec, + failureModelSpec = failureModelSpec, + checkpointModelSpec = checkpointModelSpec, + carbonTracePath = carbonTracePath, + exportModelSpec = exportModelSpec, + outputFolder = outputFolder, + name = scenarioID.toString(), + runs = scenarioSpec.runs, + initialSeed = scenarioSpec.initialSeed, + ) + trackScenario(scenarioSpec, outputFolder, scenario) + scenarios.add(scenario) + } } } } @@ -112,19 +112,19 @@ public fun trackScenario( scenarioSpec: ScenarioSpec, outputFolder: String, scenario: Scenario, - topologySpec: ScenarioTopologySpec, ) { - val trackrPath = outputFolder + "/trackr.json" + val trackrPath = "$outputFolder/trackr.json" scenarioWriter.write( ScenarioSpec( id = scenario.id, name = scenarioSpec.name, - topologies = listOf(topologySpec), - workloads = listOf(scenario.workload), - allocationPolicies = listOf(scenario.allocationPolicy), - // when implemented, add failure models here + topologies = listOf(scenario.topologySpec), + workloads = listOf(scenario.workloadSpec), + allocationPolicies = listOf(scenario.allocationPolicySpec), + failureModels = listOf(scenario.failureModelSpec), + checkpointModels = listOf(scenario.checkpointModelSpec), carbonTracePaths = listOf(scenario.carbonTracePath), - exportModels = listOf(scenario.exportModel), + exportModels = listOf(scenario.exportModelSpec), outputFolder = scenario.outputFolder, initialSeed = scenario.initialSeed, runs = scenario.runs, diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioReader.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioReader.kt index 19ce5a14..3bbd500b 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioReader.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioReader.kt @@ -28,14 +28,25 @@ import kotlinx.serialization.json.decodeFromStream import org.opendc.experiments.base.scenario.specs.ScenarioSpec import java.io.File import java.io.InputStream +import java.nio.file.Path +import kotlin.io.path.inputStream public class ScenarioReader { +// private val jsonReader = Json { serializersModule = failureModule } + private val jsonReader = Json + @OptIn(ExperimentalSerializationApi::class) public fun read(file: File): ScenarioSpec { val input = file.inputStream() - val obj = Json.decodeFromStream<ScenarioSpec>(input) - return obj + return jsonReader.decodeFromStream<ScenarioSpec>(input) + } + + @OptIn(ExperimentalSerializationApi::class) + public fun read(path: Path): ScenarioSpec { + val input = path.inputStream() + + return jsonReader.decodeFromStream<ScenarioSpec>(input) } /** @@ -43,7 +54,6 @@ public class ScenarioReader { */ @OptIn(ExperimentalSerializationApi::class) public fun read(input: InputStream): ScenarioSpec { - val obj = Json.decodeFromStream<ScenarioSpec>(input) - return obj + return jsonReader.decodeFromStream<ScenarioSpec>(input) } } diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/CheckpointModelSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/CheckpointModelSpec.kt new file mode 100644 index 00000000..9432fc9b --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/CheckpointModelSpec.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 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. + */ + +import kotlinx.serialization.Serializable + +@Serializable +public data class CheckpointModelSpec( + val checkpointWait: Long = 60 * 60 * 1000, + val checkpointTime: Long = 5 * 60 * 1000, +) diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/FailureModelSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/FailureModelSpec.kt index 99620366..a27e77bc 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/FailureModelSpec.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/FailureModelSpec.kt @@ -20,18 +20,301 @@ * SOFTWARE. */ +package org.opendc.experiments.base.scenario.specs + +/* + * Copyright (c) 2024 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. + */ + +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import org.apache.commons.math3.distribution.ConstantRealDistribution +import org.apache.commons.math3.distribution.ExponentialDistribution +import org.apache.commons.math3.distribution.GammaDistribution +import org.apache.commons.math3.distribution.LogNormalDistribution +import org.apache.commons.math3.distribution.NormalDistribution +import org.apache.commons.math3.distribution.ParetoDistribution +import org.apache.commons.math3.distribution.RealDistribution +import org.apache.commons.math3.distribution.UniformRealDistribution +import org.apache.commons.math3.distribution.WeibullDistribution +import org.apache.commons.math3.random.Well19937c +import org.opendc.compute.failure.models.FailureModel +import org.opendc.compute.failure.models.SampleBasedFailureModel +import org.opendc.compute.failure.models.TraceBasedFailureModel +import org.opendc.compute.failure.prefab.FailurePrefab +import org.opendc.compute.failure.prefab.createFailureModelPrefab +import org.opendc.compute.service.ComputeService +import java.io.File +import java.time.InstantSource +import kotlin.coroutines.CoroutineContext /** - * specification describing the failure model + * Specifications of the different Failure models + * There are three types of Specs that can be used by using their SerialName as the type. * - * @property failureInterval The interval between failures in s. Should be 0.0 or higher + * @constructor Create empty Failure model spec */ + +@Serializable +public sealed interface FailureModelSpec { + public var name: String +} + +/** + * A failure model spec for failure models based on a failure trace. + * + * @property pathToFile Path to the parquet file that contains the failure trace + */ +@Serializable +@SerialName("trace-based") +public data class TraceBasedFailureModelSpec( + public val pathToFile: String, +) : FailureModelSpec { + override var name: String = File(pathToFile).nameWithoutExtension + + init { + require(File(pathToFile).exists()) { "Path to file $pathToFile does not exist" } + } +} + +/** + * A specification for a failure model that is already present in OpenDC. + * + * @property prefabName The name of the prefab. It needs to be valid [FailurePrefab] + */ +@Serializable +@SerialName("prefab") +public data class PrefabFailureModelSpec( + public val prefabName: FailurePrefab, +) : FailureModelSpec { + override var name: String = prefabName.toString() +} + +/** + * Specification of a custom failure model that is defined by three distributions to sample from. + * Distributions are defined using a [DistributionSpec]. + * + * @property iatSampler Sampler for the time between failures defined in hours + * @property durationSampler Sampler for the time of a failure defined in hours + * @property nohSampler Sampler for ratio of hosts that fail defined as a double between 0.0 and 1.0 + * @constructor Create empty Custom failure model spec + */ +@Serializable +@SerialName("custom") +public data class CustomFailureModelSpec( + public val iatSampler: DistributionSpec, + public val durationSampler: DistributionSpec, + public val nohSampler: DistributionSpec, +) : FailureModelSpec { + override var name: String = "custom" +} + +/** + * Specifications of the different Distributions that can used to create a [CustomFailureModelSpec] + * All [DistributionSpec]s have a different definition based on the variables they need to function. + * Available [DistributionSpec] are: + * - [ConstantDistributionSpec] + * - [ExponentialDistributionSpec] + * - [GammaDistributionSpec] + * - [LogNormalDistributionSpec] + * - [ParetoDistributionSpec] + * - [UniformDistributionSpec] + * - [WeibullDistributionSpec] +*/ + +@Serializable +public sealed interface DistributionSpec + @Serializable -public data class FailureModelSpec( - val failureInterval: Double = 0.0, -) { +@SerialName("constant") +public data class ConstantDistributionSpec( + public val value: Double, +) : DistributionSpec { init { - require(failureInterval >= 0.0) { "failure frequency cannot be lower than 0" } + require(value > 0.0) { "Value must be greater than 0.0" } + } +} + +@Serializable +@SerialName("exponential") +public data class ExponentialDistributionSpec( + public val mean: Double, +) : DistributionSpec + +@Serializable +@SerialName("gamma") +public data class GammaDistributionSpec( + public val shape: Double, + public val scale: Double, +) : DistributionSpec + +@Serializable +@SerialName("log-normal") +public data class LogNormalDistributionSpec( + public val scale: Double, + public val shape: Double, +) : DistributionSpec + +@Serializable +@SerialName("normal") +public data class NormalDistributionSpec( + public val mean: Double, + public val std: Double, +) : DistributionSpec + +@Serializable +@SerialName("pareto") +public data class ParetoDistributionSpec( + public val scale: Double, + public val shape: Double, +) : DistributionSpec + +@Serializable +@SerialName("uniform") +public data class UniformDistributionSpec( + public val upper: Double, + public val lower: Double, +) : DistributionSpec { + init { + require(upper > lower) { "Upper bound must be greater than the lower bound" } + } +} + +@Serializable +@SerialName("weibull") +public data class WeibullDistributionSpec( + public val alpha: Double, + public val beta: Double, +) : DistributionSpec + +/** + * Create a [FailureModel] based on the provided [FailureModelSpec] + * + * @param context + * @param clock + * @param service + * @param random + * @param failureModelSpec + * @return + */ +public fun createFailureModel( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: java.util.random.RandomGenerator, + failureModelSpec: FailureModelSpec?, +): FailureModel? { + return when (failureModelSpec) { + is PrefabFailureModelSpec -> createFailureModel(context, clock, service, random, failureModelSpec) + is CustomFailureModelSpec -> createFailureModel(context, clock, service, random, failureModelSpec) + is TraceBasedFailureModelSpec -> createFailureModel(context, clock, service, random, failureModelSpec) + else -> null + } +} + +/** + * Create [FailureModel] based on the provided [PrefabFailureModelSpec] + * + * @param context + * @param clock + * @param service + * @param random + * @param failureModel + * @return + */ +public fun createFailureModel( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: java.util.random.RandomGenerator, + failureModel: PrefabFailureModelSpec, +): FailureModel { + return createFailureModelPrefab(context, clock, service, random, failureModel.prefabName) +} + +/** + * Create [FailureModel] based on the provided [TraceBasedFailureModel] + * + * @param context + * @param clock + * @param service + * @param random + * @param failureModel + * @return + */ +public fun createFailureModel( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: java.util.random.RandomGenerator, + failureModel: TraceBasedFailureModelSpec, +): FailureModel { + return TraceBasedFailureModel(context, clock, service, random, failureModel.pathToFile) +} + +/** + * Create [FailureModel] based on the provided [CustomFailureModelSpec] + * + * @param context + * @param clock + * @param service + * @param random + * @param failureModel + * @return + */ +public fun createFailureModel( + context: CoroutineContext, + clock: InstantSource, + service: ComputeService, + random: java.util.random.RandomGenerator, + failureModel: CustomFailureModelSpec, +): FailureModel { + val rng: org.apache.commons.math3.random.RandomGenerator = Well19937c(random.nextLong()) + + val iatSampler = createSampler(rng, failureModel.iatSampler) + val durationSampler = createSampler(rng, failureModel.durationSampler) + val nohSampler = createSampler(rng, failureModel.nohSampler) + + return SampleBasedFailureModel(context, clock, service, random, iatSampler, durationSampler, nohSampler) +} + +/** + * Create a [RealDistribution] to sample from based on the provided [DistributionSpec] + * + * @param rng + * @param distributionSpec + * @return + */ +public fun createSampler( + rng: org.apache.commons.math3.random.RandomGenerator, + distributionSpec: DistributionSpec, +): RealDistribution { + return when (distributionSpec) { + is ConstantDistributionSpec -> ConstantRealDistribution(distributionSpec.value) + is ExponentialDistributionSpec -> ExponentialDistribution(rng, distributionSpec.mean) + is GammaDistributionSpec -> GammaDistribution(rng, distributionSpec.shape, distributionSpec.scale) + is LogNormalDistributionSpec -> LogNormalDistribution(rng, distributionSpec.scale, distributionSpec.shape) + is NormalDistributionSpec -> NormalDistribution(rng, distributionSpec.mean, distributionSpec.std) + is ParetoDistributionSpec -> ParetoDistribution(rng, distributionSpec.scale, distributionSpec.shape) + is UniformDistributionSpec -> UniformRealDistribution(rng, distributionSpec.lower, distributionSpec.upper) + is WeibullDistributionSpec -> WeibullDistribution(rng, distributionSpec.alpha, distributionSpec.beta) } } diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt index 876a62cf..eb3cd04e 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt @@ -23,8 +23,8 @@ package org.opendc.experiments.base.scenario.specs import AllocationPolicySpec +import CheckpointModelSpec import ExportModelSpec -import FailureModelSpec import ScenarioTopologySpec import WorkloadSpec import kotlinx.serialization.Serializable @@ -49,7 +49,8 @@ public data class ScenarioSpec( val topologies: List<ScenarioTopologySpec>, val workloads: List<WorkloadSpec>, val allocationPolicies: List<AllocationPolicySpec>, - val failureModels: List<FailureModelSpec> = listOf(FailureModelSpec()), + val failureModels: List<FailureModelSpec?> = listOf(null), + val checkpointModels: List<CheckpointModelSpec?> = listOf(null), val carbonTracePaths: List<String?> = listOf(null), val exportModels: List<ExportModelSpec> = listOf(ExportModelSpec()), val outputFolder: String = "output", diff --git a/opendc-experiments/opendc-experiments-scenario/src/main/resources/scenario.json b/opendc-experiments/opendc-experiments-scenario/src/main/resources/scenario.json index 854d9b8f..3b22e5f4 100644 --- a/opendc-experiments/opendc-experiments-scenario/src/main/resources/scenario.json +++ b/opendc-experiments/opendc-experiments-scenario/src/main/resources/scenario.json @@ -9,5 +9,8 @@ }, "allocationPolicy": { "policyType": "Mem" + }, + "failureModel": { + "name": "TEST" } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/CPUPowerModelsFactory.kt b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/CPUPowerModelsFactory.kt index e2f852f8..2c64944c 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/CPUPowerModelsFactory.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/CPUPowerModelsFactory.kt @@ -22,6 +22,15 @@ package org.opendc.simulator.compute.power +// TODO: couple this correctly +public enum class CPUPowerModel { + Constant, + Sqrt, + Linear, + Square, + Cubic, +} + public fun getPowerModel( modelType: String, power: Double, diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java index bf54142f..c116a5e5 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java @@ -34,7 +34,7 @@ import org.opendc.simulator.flow2.OutPort; * A [SimWorkload] that models application execution as a single duration. */ public class SimRuntimeWorkload implements SimWorkload, FlowStageLogic { - private final long duration; + private long duration; private final double utilization; private SimMachineContext ctx; @@ -44,20 +44,52 @@ public class SimRuntimeWorkload implements SimWorkload, FlowStageLogic { private long remainingDuration; private long lastUpdate; + private long checkpointTime; // How long does it take to make a checkpoint? + private long checkpointWait; // How long to wait until a new checkpoint is made? + private long totalChecks; + + public SimRuntimeWorkload(long duration, double utilization) { + this(duration, utilization, 0, 0); + // if (duration < 0) { + // throw new IllegalArgumentException("Duration must be positive"); + // } else if (utilization <= 0.0 || utilization > 1.0) { + // throw new IllegalArgumentException("Utilization must be in (0, 1]"); + // } + // + // this.checkpointTime = 0L; + // this.checkpointWait = 0L; + // this.duration = duration; + // + // this.utilization = utilization; + // this.remainingDuration = duration; + } + /** * Construct a new {@link SimRuntimeWorkload}. * * @param duration The duration of the workload in milliseconds. * @param utilization The CPU utilization of the workload. */ - SimRuntimeWorkload(long duration, double utilization) { + public SimRuntimeWorkload(long duration, double utilization, long checkpointTime, long checkpointWait) { if (duration < 0) { throw new IllegalArgumentException("Duration must be positive"); } else if (utilization <= 0.0 || utilization > 1.0) { throw new IllegalArgumentException("Utilization must be in (0, 1]"); } + this.checkpointTime = checkpointTime; + this.checkpointWait = checkpointWait; this.duration = duration; + + if (this.checkpointWait > 0) { + // Determine the number of checkpoints that need to be made during the workload + // If the total duration is divisible by the wait time between checkpoints, we can remove the last + // checkpoint + int to_remove = ((this.duration % this.checkpointWait == 0) ? 1 : 0); + this.totalChecks = this.duration / this.checkpointWait - to_remove; + this.duration += (this.checkpointTime * totalChecks); + } + this.utilization = utilization; this.remainingDuration = duration; } @@ -108,7 +140,25 @@ public class SimRuntimeWorkload implements SimWorkload, FlowStageLogic { stage.sync(); } - return new SimRuntimeWorkload(remainingDuration, utilization); + var remaining_time = this.remainingDuration; + + if (this.checkpointWait > 0) { + // Calculate last checkpoint + var total_check_time = this.checkpointWait + this.checkpointTime; + var processed_time = this.duration - this.remainingDuration; + var processed_checks = (int) (processed_time / total_check_time); + var processed_time_last_check = + (processed_checks * total_check_time); // The processed time after the last checkpoint + + remaining_time = this.duration + - processed_time_last_check; // The remaining duration to process after last checkpoint + var remaining_checks = (int) (remaining_time / total_check_time); + remaining_time -= (remaining_checks * checkpointTime); + } else { + remaining_time = duration; + } + + return new SimRuntimeWorkload(remaining_time, utilization, this.checkpointTime, this.checkpointWait); } @Override @@ -119,6 +169,12 @@ public class SimRuntimeWorkload implements SimWorkload, FlowStageLogic { long delta = now - lastUpdate; long duration = this.remainingDuration - delta; + if (delta == 0 && this.ctx == null) { + // This means the workload has been terminated + // But, has not executed to completion + return Long.MAX_VALUE; + } + if (duration <= 0) { final SimMachineContext machineContext = this.ctx; if (machineContext != null) { diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java index f2f4ce45..21379f0d 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java @@ -71,7 +71,16 @@ public final class SimTrace { * // * @param offset The offset for the timestamps. */ public SimWorkload createWorkload(long start) { - return new Workload(start, usageCol, deadlineCol, coresCol, size, 0); + return createWorkload(start, 0, 0); + } + + /** + * Construct a {@link SimWorkload} for this trace. + * + * // * @param offset The offset for the timestamps. + */ + public SimWorkload createWorkload(long start, long checkpointTime, long checkpointWait) { + return new Workload(start, usageCol, deadlineCol, coresCol, size, 0, checkpointTime, checkpointWait); } /** @@ -215,13 +224,27 @@ public final class SimTrace { private final int size; private final int index; - private Workload(long start, double[] usageCol, long[] deadlineCol, int[] coresCol, int size, int index) { + private long checkpointTime; // How long does it take to make a checkpoint? + private long checkpointWait; // How long to wait until a new checkpoint is made? + private long total_checks; + + private Workload( + long start, + double[] usageCol, + long[] deadlineCol, + int[] coresCol, + int size, + int index, + long checkpointTime, + long checkpointWait) { this.start = start; this.usageCol = usageCol; this.deadlineCol = deadlineCol; this.coresCol = coresCol; this.size = size; this.index = index; + this.checkpointTime = checkpointTime; + this.checkpointWait = checkpointWait; } @Override @@ -259,7 +282,7 @@ public final class SimTrace { index = logic.getIndex(); } - return new Workload(start, usageCol, deadlineCol, coresCol, size, index); + return new Workload(start, usageCol, deadlineCol, coresCol, size, index, checkpointTime, checkpointWait); } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimWorkloads.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimWorkloads.java index 82557d06..294b5dde 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimWorkloads.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimWorkloads.java @@ -48,7 +48,17 @@ public class SimWorkloads { * @param utilization The CPU utilization of the workload. */ public static SimWorkload runtime(long duration, double utilization) { - return new SimRuntimeWorkload(duration, utilization); + return runtime(duration, utilization, 0, 0); + } + + /** + * Create a {@link SimWorkload} that consumes the CPU resources for a specified duration at the given utilization. + * + * @param duration The duration of the workload in milliseconds. + * @param utilization The CPU utilization of the workload. + */ + public static SimWorkload runtime(long duration, double utilization, long checkpoint_time, long checkpoint_wait) { + return new SimRuntimeWorkload(duration, utilization, checkpoint_time, checkpoint_wait); } /** @@ -57,8 +67,9 @@ public class SimWorkloads { * @param duration The duration of the workload. * @param utilization The CPU utilization of the workload. */ - public static SimWorkload runtime(Duration duration, double utilization) { - return runtime(duration.toMillis(), utilization); + public static SimWorkload runtime( + Duration duration, double utilization, long checkpoint_time, long checkpoint_wait) { + return runtime(duration.toMillis(), utilization, checkpoint_time, checkpoint_wait); } /** diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt index 9ea9d300..a0301dda 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt @@ -74,8 +74,8 @@ class SimChainWorkloadTest { val workload = SimWorkloads.chain( - SimWorkloads.runtime(1000, 1.0), - SimWorkloads.runtime(1000, 1.0), + SimWorkloads.runtime(1000, 1.0, 0L, 0L), + SimWorkloads.runtime(1000, 1.0, 0L, 0L), ) machine.runWorkload(workload) @@ -102,7 +102,7 @@ class SimChainWorkloadTest { val workload = SimWorkloads.chain( workloadA, - SimWorkloads.runtime(1000, 1.0), + SimWorkloads.runtime(1000, 1.0, 0L, 0L), ) assertThrows<IllegalStateException> { machine.runWorkload(workload) } @@ -300,6 +300,6 @@ class SimChainWorkloadTest { machine.runWorkload(snapshot) - assertEquals(3500, timeSource.millis()) + assertEquals(4000, timeSource.millis()) } } diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/FailureColumns.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/FailureColumns.kt new file mode 100644 index 00000000..3f653041 --- /dev/null +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/FailureColumns.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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. + */ + +@file:JvmName("FailureColumns") + +package org.opendc.trace.conv + +/** + * A column containing the task identifier. + */ +public const val FAILURE_INTERVAL: String = "failure_interval" + +/** + * A column containing the task identifier. + */ +public const val FAILURE_DURATION: String = "failure_duration" + +/** + * A column containing the task identifier. + */ +public const val FAILURE_INTENSITY: String = "failure_intensity" diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/Tables.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/Tables.kt index 9b8fc6cf..d4019f73 100644 --- a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/Tables.kt +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/Tables.kt @@ -49,4 +49,6 @@ public const val TABLE_RESOURCE_STATES: String = "resource_states" */ public const val TABLE_INTERFERENCE_GROUPS: String = "interference_groups" -public const val TABLE_CARBON_INTENSITY: String = "carbon_intensities" +public const val TABLE_CARBON_INTENSITIES: String = "carbon_intensities" + +public const val TABLE_FAILURES: String = "failures" diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/carbon/CarbonTraceFormat.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/carbon/CarbonTraceFormat.kt index 0daa1297..d8adc739 100644 --- a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/carbon/CarbonTraceFormat.kt +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/carbon/CarbonTraceFormat.kt @@ -28,7 +28,7 @@ import org.opendc.trace.TableReader import org.opendc.trace.TableWriter import org.opendc.trace.conv.CARBON_INTENSITY_TIMESTAMP import org.opendc.trace.conv.CARBON_INTENSITY_VALUE -import org.opendc.trace.conv.TABLE_CARBON_INTENSITY +import org.opendc.trace.conv.TABLE_CARBON_INTENSITIES import org.opendc.trace.formats.carbon.parquet.CarbonIntensityReadSupport import org.opendc.trace.spi.TableDetails import org.opendc.trace.spi.TraceFormat @@ -45,14 +45,14 @@ public class CarbonTraceFormat : TraceFormat { throw UnsupportedOperationException("Writing not supported for this format") } - override fun getTables(path: Path): List<String> = listOf(TABLE_CARBON_INTENSITY) + override fun getTables(path: Path): List<String> = listOf(TABLE_CARBON_INTENSITIES) override fun getDetails( path: Path, table: String, ): TableDetails { return when (table) { - TABLE_CARBON_INTENSITY -> + TABLE_CARBON_INTENSITIES -> TableDetails( listOf( TableColumn(CARBON_INTENSITY_TIMESTAMP, TableColumnType.Instant), @@ -69,7 +69,7 @@ public class CarbonTraceFormat : TraceFormat { projection: List<String>?, ): TableReader { return when (table) { - TABLE_CARBON_INTENSITY -> { + TABLE_CARBON_INTENSITIES -> { val reader = LocalParquetReader(path, CarbonIntensityReadSupport(projection)) CarbonTableReader(reader) } diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTableReader.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTableReader.kt new file mode 100644 index 00000000..a1c10bd0 --- /dev/null +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTableReader.kt @@ -0,0 +1,144 @@ +/* + * 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.trace.formats.failure + +import org.opendc.trace.TableReader +import org.opendc.trace.conv.FAILURE_DURATION +import org.opendc.trace.conv.FAILURE_INTENSITY +import org.opendc.trace.conv.FAILURE_INTERVAL +import org.opendc.trace.formats.failure.parquet.FailureFragment +import org.opendc.trace.util.parquet.LocalParquetReader +import java.time.Duration +import java.time.Instant +import java.util.UUID + +/** + * A [TableReader] implementation for the WTF format. + */ +internal class FailureTableReader(private val reader: LocalParquetReader<FailureFragment>) : TableReader { + /** + * The current record. + */ + private var record: FailureFragment? = null + + override fun nextRow(): Boolean { + try { + val record = reader.read() + this.record = record + + return record != null + } catch (e: Throwable) { + this.record = null + throw e + } + } + + private val colFailureInterval = 0 + private val colFailureDuration = 1 + private val colFailureIntensity = 2 + + override fun resolve(name: String): Int { + return when (name) { + FAILURE_INTERVAL -> colFailureInterval + FAILURE_DURATION -> colFailureDuration + FAILURE_INTENSITY -> colFailureIntensity + else -> -1 + } + } + + override fun isNull(index: Int): Boolean { + require(index in colFailureInterval..colFailureIntensity) { "Invalid column index" } + return false + } + + override fun getBoolean(index: Int): Boolean { + throw IllegalArgumentException("Invalid column") + } + + override fun getInt(index: Int): Int { + throw IllegalArgumentException("Invalid column") + } + + override fun getLong(index: Int): Long { + val record = checkNotNull(record) { "Reader in invalid state" } + return when (index) { + colFailureInterval -> record.failureInterval + colFailureDuration -> record.failureDuration + else -> throw IllegalArgumentException("Invalid column") + } + } + + override fun getFloat(index: Int): Float { + throw IllegalArgumentException("Invalid column") + } + + override fun getDouble(index: Int): Double { + val record = checkNotNull(record) { "Reader in invalid state" } + return when (index) { + colFailureIntensity -> record.failureIntensity + else -> throw IllegalArgumentException("Invalid column") + } + } + + override fun getString(index: Int): String { + throw IllegalArgumentException("Invalid column") + } + + override fun getUUID(index: Int): UUID? { + throw IllegalArgumentException("Invalid column") + } + + override fun getInstant(index: Int): Instant { + throw IllegalArgumentException("Invalid column") + } + + override fun getDuration(index: Int): Duration { + throw IllegalArgumentException("Invalid column") + } + + override fun <T> getList( + index: Int, + elementType: Class<T>, + ): List<T>? { + throw IllegalArgumentException("Invalid column") + } + + override fun <T> getSet( + index: Int, + elementType: Class<T>, + ): Set<T>? { + throw IllegalArgumentException("Invalid column") + } + + override fun <K, V> getMap( + index: Int, + keyType: Class<K>, + valueType: Class<V>, + ): Map<K, V>? { + throw IllegalArgumentException("Invalid column") + } + + override fun close() { + reader.close() + } +} diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTraceFormat.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTraceFormat.kt new file mode 100644 index 00000000..892216a0 --- /dev/null +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTraceFormat.kt @@ -0,0 +1,88 @@ +/* + * 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.trace.formats.failure + +import org.opendc.trace.TableColumn +import org.opendc.trace.TableColumnType +import org.opendc.trace.TableReader +import org.opendc.trace.TableWriter +import org.opendc.trace.conv.FAILURE_DURATION +import org.opendc.trace.conv.FAILURE_INTENSITY +import org.opendc.trace.conv.FAILURE_INTERVAL +import org.opendc.trace.conv.TABLE_FAILURES +import org.opendc.trace.formats.failure.parquet.FailureReadSupport +import org.opendc.trace.spi.TableDetails +import org.opendc.trace.spi.TraceFormat +import org.opendc.trace.util.parquet.LocalParquetReader +import java.nio.file.Path + +/** + * A [TraceFormat] implementation for the Failure Intensity trace. + */ +public class FailureTraceFormat : TraceFormat { + override val name: String = "failure" + + override fun create(path: Path) { + throw UnsupportedOperationException("Writing not supported for this format") + } + + override fun getTables(path: Path): List<String> = listOf(TABLE_FAILURES) + + override fun getDetails( + path: Path, + table: String, + ): TableDetails { + return when (table) { + TABLE_FAILURES -> + TableDetails( + listOf( + TableColumn(FAILURE_INTERVAL, TableColumnType.Long), + TableColumn(FAILURE_DURATION, TableColumnType.Long), + TableColumn(FAILURE_INTENSITY, TableColumnType.Double), + ), + ) + else -> throw IllegalArgumentException("Table $table not supported") + } + } + + override fun newReader( + path: Path, + table: String, + projection: List<String>?, + ): TableReader { + return when (table) { + TABLE_FAILURES -> { + val reader = LocalParquetReader(path, FailureReadSupport(projection)) + FailureTableReader(reader) + } + else -> throw IllegalArgumentException("Table $table not supported") + } + } + + override fun newWriter( + path: Path, + table: String, + ): TableWriter { + throw UnsupportedOperationException("Writing not supported for this format") + } +} diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureFragment.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureFragment.kt new file mode 100644 index 00000000..49f43aa1 --- /dev/null +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureFragment.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 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.trace.formats.failure.parquet + +/** + * A task in the Workflow Trace Format. + */ +internal data class FailureFragment( + val failureInterval: Long, + val failureDuration: Long, + val failureIntensity: Double, +) diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureReadSupport.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureReadSupport.kt new file mode 100644 index 00000000..d49f86c6 --- /dev/null +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureReadSupport.kt @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022 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.trace.formats.failure.parquet + +import org.apache.hadoop.conf.Configuration +import org.apache.parquet.hadoop.api.InitContext +import org.apache.parquet.hadoop.api.ReadSupport +import org.apache.parquet.io.api.RecordMaterializer +import org.apache.parquet.schema.MessageType +import org.apache.parquet.schema.PrimitiveType +import org.apache.parquet.schema.Types +import org.opendc.trace.conv.FAILURE_DURATION +import org.opendc.trace.conv.FAILURE_INTENSITY +import org.opendc.trace.conv.FAILURE_INTERVAL + +/** + * A [ReadSupport] instance for [Task] objects. + * + * @param projection The projection of the table to read. + */ +internal class FailureReadSupport(private val projection: List<String>?) : ReadSupport<FailureFragment>() { + /** + * Mapping of table columns to their Parquet column names. + */ + private val colMap = + mapOf( + FAILURE_INTERVAL to "interval", + FAILURE_DURATION to "duration", + FAILURE_INTENSITY to "intensity", + ) + + override fun init(context: InitContext): ReadContext { + val projectedSchema = + if (projection != null) { + Types.buildMessage() + .apply { + val fieldByName = READ_SCHEMA.fields.associateBy { it.name } + + for (col in projection) { + val fieldName = colMap[col] ?: continue + addField(fieldByName.getValue(fieldName)) + } + } + .named(READ_SCHEMA.name) + } else { + READ_SCHEMA + } + return ReadContext(projectedSchema) + } + + override fun prepareForRead( + configuration: Configuration, + keyValueMetaData: Map<String, String>, + fileSchema: MessageType, + readContext: ReadContext, + ): RecordMaterializer<FailureFragment> = FailureRecordMaterializer(readContext.requestedSchema) + + companion object { + /** + * Parquet read schema for the "tasks" table in the trace. + */ + @JvmStatic + val READ_SCHEMA: MessageType = + Types.buildMessage() + .addFields( + Types + .optional(PrimitiveType.PrimitiveTypeName.INT64) + .named("failure_interval"), + Types + .optional(PrimitiveType.PrimitiveTypeName.INT64) + .named("failure_duration"), + Types + .optional(PrimitiveType.PrimitiveTypeName.DOUBLE) + .named("failure_intensity"), + ) + .named("failure_fragment") + } +} diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureRecordMaterializer.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureRecordMaterializer.kt new file mode 100644 index 00000000..5a00f8c9 --- /dev/null +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureRecordMaterializer.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 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.trace.formats.failure.parquet + +import org.apache.parquet.io.api.Converter +import org.apache.parquet.io.api.GroupConverter +import org.apache.parquet.io.api.PrimitiveConverter +import org.apache.parquet.io.api.RecordMaterializer +import org.apache.parquet.schema.MessageType + +/** + * A [RecordMaterializer] for [Task] records. + */ +internal class FailureRecordMaterializer(schema: MessageType) : RecordMaterializer<FailureFragment>() { + /** + * State of current record being read. + */ + private var localFailureInterval: Long = 0L + private var localFailureDuration: Long = 0L + private var localFailureIntensity: Double = 0.0 + + /** + * Root converter for the record. + */ + private val root = + object : GroupConverter() { + /** + * The converters for the columns of the schema. + */ + private val converters = + schema.fields.map { type -> + when (type.name) { + "failure_interval" -> + object : PrimitiveConverter() { + override fun addLong(value: Long) { + localFailureInterval = value + } + } + "failure_duration" -> + object : PrimitiveConverter() { + override fun addLong(value: Long) { + localFailureDuration = value + } + } + "failure_intensity" -> + object : PrimitiveConverter() { + override fun addDouble(value: Double) { + localFailureIntensity = value + } + } + else -> error("Unknown column $type") + } + } + + override fun start() { + localFailureInterval = 0L + localFailureDuration = 0L + localFailureIntensity = 0.0 + } + + override fun end() {} + + override fun getConverter(fieldIndex: Int): Converter = converters[fieldIndex] + } + + override fun getCurrentRecord(): FailureFragment = + FailureFragment( + localFailureInterval, + localFailureDuration, + localFailureIntensity, + ) + + override fun getRootConverter(): GroupConverter = root +} diff --git a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/spi/TraceFormat.kt b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/spi/TraceFormat.kt index 67df667b..e586f90a 100644 --- a/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/spi/TraceFormat.kt +++ b/opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/spi/TraceFormat.kt @@ -27,6 +27,7 @@ import org.opendc.trace.TableWriter import org.opendc.trace.azure.AzureTraceFormat import org.opendc.trace.bitbrains.BitbrainsTraceFormat import org.opendc.trace.formats.carbon.CarbonTraceFormat +import org.opendc.trace.formats.failure.FailureTraceFormat import org.opendc.trace.formats.opendc.OdcVmTraceFormat import org.opendc.trace.gwf.GwfTraceFormat import org.opendc.trace.swf.SwfTraceFormat @@ -124,6 +125,7 @@ public interface TraceFormat { "azure" -> AzureTraceFormat() "bitbrains" -> BitbrainsTraceFormat() "carbon" -> CarbonTraceFormat() + "failure" -> FailureTraceFormat() "gwf" -> GwfTraceFormat() "opendc-vm" -> OdcVmTraceFormat() "swf" -> SwfTraceFormat() diff --git a/opendc-web/opendc-web-runner/build.gradle.kts b/opendc-web/opendc-web-runner/build.gradle.kts index d5d1dbc6..40f94644 100644 --- a/opendc-web/opendc-web-runner/build.gradle.kts +++ b/opendc-web/opendc-web-runner/build.gradle.kts @@ -58,6 +58,7 @@ dependencies { implementation(project(mapOf("path" to ":opendc-experiments:opendc-experiments-base"))) implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-topology"))) implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-telemetry"))) + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-failure"))) cliImplementation(libs.clikt) diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt index d6913412..7eb6e21f 100644 --- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt +++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt @@ -23,9 +23,10 @@ package org.opendc.web.runner import mu.KotlinLogging +import org.opendc.compute.failure.prefab.FailurePrefab +import org.opendc.compute.failure.prefab.createFailureModelPrefab import org.opendc.compute.service.ComputeService import org.opendc.compute.service.scheduler.createComputeScheduler -import org.opendc.compute.simulator.failure.models.Grid5000 import org.opendc.compute.simulator.provisioner.Provisioner import org.opendc.compute.simulator.provisioner.registerComputeMonitor import org.opendc.compute.simulator.provisioner.setupComputeService @@ -282,7 +283,7 @@ public class OpenDCRunner( val phenomena = scenario.phenomena val failureModel = if (phenomena.failures) { - Grid5000(Duration.ofDays(7)) + createFailureModelPrefab(coroutineContext, timeSource, service, Random(seed), FailurePrefab.G5k06Exp) } else { null } diff --git a/settings.gradle.kts b/settings.gradle.kts index 3e3ac677..d01d1261 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,12 +23,13 @@ rootProject.name = "opendc" include(":opendc-common") include(":opendc-compute:opendc-compute-api") +include(":opendc-compute:opendc-compute-carbon") +include(":opendc-compute:opendc-compute-failure") include(":opendc-compute:opendc-compute-service") +include(":opendc-compute:opendc-compute-simulator") include(":opendc-compute:opendc-compute-telemetry") include(":opendc-compute:opendc-compute-topology") -include(":opendc-compute:opendc-compute-simulator") include(":opendc-compute:opendc-compute-workload") -include(":opendc-compute:opendc-compute-carbon") include(":opendc-workflow:opendc-workflow-api") include(":opendc-workflow:opendc-workflow-service") include(":opendc-faas:opendc-faas-api") @@ -57,6 +58,7 @@ include(":opendc-trace:opendc-trace-api") include(":opendc-trace:opendc-trace-calcite") include(":opendc-trace:opendc-trace-parquet") include(":opendc-trace:opendc-trace-testkit") +include(":opendc-trace:opendc-trace-failure") include(":opendc-trace:opendc-trace-tools") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") diff --git a/site/docs/documentation/Input/FailureModels.md b/site/docs/documentation/Input/FailureModels.md new file mode 100644 index 00000000..d62767f6 --- /dev/null +++ b/site/docs/documentation/Input/FailureModels.md @@ -0,0 +1,202 @@ +OpenDC provides three types of failure models: [Trace-based](#trace-based-failure-models), [Sample-based](#sample-based-failure-models), +and [Prefab](#prefab-failure-models). + +All failure models have a similar structure containing three simple steps. + +1. The _interval_ time determines the time between two failures. +2. The _duration_ time determines how long a single failure takes. +3. The _intensity_ determines how many hosts are effected by a failure. + +# Trace based failure models +Trace-based failure models are defined by a parquet file. This file defines the interval, duration, and intensity of +several failures. The failures defined in the file are looped. A valid failure model file follows the format defined below: + +| Metric | Datatype | Unit | Summary | +|-------------------|------------|---------------|--------------------------------------------| +| failure_interval | int64 | milli seconds | The duration since the last failure | +| failure_duration | int64 | milli seconds | The duration of the failure | +| failure_intensity | float64 | ratio | The ratio of hosts effected by the failure | + +## Schema +A trace-based failure model is specified by setting "type" to "trace-based". +After, the user can define the path to the failure trace using "pathToFile": +```json +{ + "type": "trace-based", + "pathToFile": "path/to/your/failure_trace.parquet" +} +``` + +The "repeat" value can be set to false if the user does not want the failures to loop: +```json +{ + "type": "trace-based", + "pathToFile": "path/to/your/failure_trace.parquet", + "repeat": "false" +} +``` + +# Sample based failure models +Sample based failure models sample from three distributions to get the _interval_, _duration_, and _intensity_ of +each failure. Sample-based failure models are effected by randomness and will thus create different results based +on the provided seed. + +## Distributions +OpenDC supports eight different distributions based on java's [RealDistributions](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/RealDistribution.html). +Because the different distributions require different variables, they have to be specified with a specific "type". + +#### [ConstantRealDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/ConstantRealDistribution.html) +A distribution that always returns the same value. + +```json +{ + "type": "constant", + "value": 10.0 +} +``` + +#### [ExponentialDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/ExponentialDistribution.html) +```json +{ + "type": "exponential", + "mean": 1.5 +} +``` + +#### [GammaDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/GammaDistribution.html) +```json +{ + "type": "gamma", + "shape": 1.0, + "scale": 0.5 +} +``` + +#### [LogNormalDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/LogNormalDistribution.html) +```json +{ + "type": "log-normal", + "scale": 1.0, + "shape": 0.5 +} +``` + +#### [NormalDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/NormalDistribution.html) +```json +{ + "type": "normal", + "mean": 1.0, + "std": 0.5 +} +``` + +#### [ParetoDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/ParetoDistribution.html) +```json +{ + "type": "constant", + "scale": 1.0, + "shape": 0.6 +} +``` + +#### [UniformRealDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/UniformRealDistribution.html) +```json +{ + "type": "constant", + "lower": 5.0, + "upper": 10.0 +} +``` + +#### [WeibullDistribution](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/WeibullDistribution.html) +```json +{ + "type": "constant", + "alpha": 0.5, + "beta": 1.2 +} +``` + +## Schema +A sample-based failure model is defined using three distributions for _intensity_, _duration_, and _intensity_. +Distributions can be mixed however the user wants. Note, values for _intensity_ and _duration_ are clamped to be positive. +The _intensity_ is clamped to the range [0.0, 1.0). +To specify a sample-based failure model, the type needs to be set to "custom". + +Example: +```json +{ + "type": "custom", + "iatSampler": { + "type": "exponential", + "mean": 1.5 + }, + "durationSampler": { + "type": "constant", + "alpha": 0.5, + "beta": 1.2 + }, + "nohSampler": { + "type": "constant", + "value": 0.5 + } +} +``` + +# Prefab failure models +The final type of failure models is the prefab models. These are models that are predefined in OpenDC and are based on +research. Currently, OpenDC has 9 prefab models based on [The Failure Trace Archive: Enabling the comparison of failure measurements and models of distributed systems](https://www-sciencedirect-com.vu-nl.idm.oclc.org/science/article/pii/S0743731513000634) +The figure below shows the values used to define the failure models. + + +Each failure model is defined four times, on for each of the four distribution. +The final list of available prefabs is thus: + + G5k06Exp + G5k06Wbl + G5k06LogN + G5k06Gam + Lanl05Exp + Lanl05Wbl + Lanl05LogN + Lanl05Gam + Ldns04Exp + Ldns04Wbl + Ldns04LogN + Ldns04Gam + Microsoft99Exp + Microsoft99Wbl + Microsoft99LogN + Microsoft99Gam + Nd07cpuExp + Nd07cpuWbl + Nd07cpuLogN + Nd07cpuGam + Overnet03Exp + Overnet03Wbl + Overnet03LogN + Overnet03Gam + Pl05Exp + Pl05Wbl + Pl05LogN + Pl05Gam + Skype06Exp + Skype06Wbl + Skype06LogN + Skype06Gam + Websites02Exp + Websites02Wbl + Websites02LogN + Websites02Gam + +## Schema +To specify a prefab model, the "type" needs to be set to "prefab". +After, the prefab can be defined with "prefabName": + +```json +{ + "type": "prefab", + "prefabName": "G5k06Exp" +} +``` + diff --git a/site/docs/documentation/Input/Scenario.md b/site/docs/documentation/Input/Scenario.md index e5c4c58c..ff7b9ffb 100644 --- a/site/docs/documentation/Input/Scenario.md +++ b/site/docs/documentation/Input/Scenario.md @@ -13,7 +13,7 @@ In the following section, we describe the different components of the schema. | name | string | no | "" | Name of the scenario, used for identification and referencing. | | topologies | List[[Topology](#topology)] | yes | N/A | List of topologies used in the scenario. | | workloads | List[[Workload](#workload)] | yes | N/A | List of workloads to be executed within the scenario. | -| allocationPolicies | List[[AllocationPolicy](#allocationpolicy)] | yes | N/A | Allocation policies used for resource management in the scenario. | +| allocationPolicies | List[[AllocationPolicy](#allocation-policy)] | yes | N/A | Allocation policies used for resource management in the scenario. | | failureModels | List[[FailureModel](#failuremodel)] | no | empty | List of failure models to simulate various types of failures. | | exportModels | List[[ExportModel](#exportmodel)] | no | empty | Specifications for exporting data from the simulation. | | carbonTracePaths | List[string] | no | null | Paths to carbon footprint trace files. | @@ -34,7 +34,7 @@ In the following section, we describe the different components of the schema. | pathToFile | string | yes | N/A | Path to the file containing the workload trace. | | type | string | yes | N/A | Type of the workload (e.g., "ComputeWorkload"). | -### AllocationPolicy +### Allocation Policy | Variable | Type | Required? | Default | Description | |-------------|--------|-----------|---------|---------------------------------------------------------------------| diff --git a/site/docs/documentation/Input/img.png b/site/docs/documentation/Input/img.png Binary files differnew file mode 100644 index 00000000..5ad3a85b --- /dev/null +++ b/site/docs/documentation/Input/img.png |
