summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opendc-compute/opendc-compute-api/build.gradle.kts3
-rw-r--r--opendc-compute/opendc-compute-api/src/main/kotlin/org/opendc/compute/api/ComputeClient.kt6
-rw-r--r--opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt12
-rw-r--r--opendc-compute/opendc-compute-failure/build.gradle.kts (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/FailureModel.kt)33
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/hostfault/HostFault.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/HostFault.kt)12
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/hostfault/StartStopHostFault.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/StartStopHostFault.kt)34
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/FailureModel.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/HostFaultInjectorImpl.kt)71
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/SampleBasedFailureModel.kt77
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/models/TraceBasedFailureModel.kt125
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/G5k06.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Lanl05.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Ldns04.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Microsoft99.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Nd07cpu.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Overnet03.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Pl05.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/PrefabFailureModelFactory.kt140
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Skype06.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/prefab/Websites02.kt115
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/victimselector/StochasticVictimSelector.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/StochasticVictimSelector.kt)39
-rw-r--r--opendc-compute/opendc-compute-failure/src/main/kotlin/org/opendc/compute/failure/victimselector/VictimSelector.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/VictimSelector.kt)16
-rw-r--r--opendc-compute/opendc-compute-failure/src/test/resources/log4j2.xml38
-rw-r--r--opendc-compute/opendc-compute-service/build.gradle.kts1
-rw-r--r--opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ComputeService.java24
-rw-r--r--opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/ServiceServer.java11
-rw-r--r--opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/FilterScheduler.kt1
-rw-r--r--opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/ComputeFilter.kt3
-rw-r--r--opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/RamFilter.kt16
-rw-r--r--opendc-compute/opendc-compute-simulator/build.gradle.kts2
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt3
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/checkpoints/CheckpointModel.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/FailureModelFactory.kt)23
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/HostFaultInjector.kt66
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/failure/models/Grid5000.kt70
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt3
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt6
-rw-r--r--opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/failure/HostFaultInjectorTest.kt119
-rw-r--r--opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyReader.kt12
-rw-r--r--opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt4
-rw-r--r--opendc-experiments/opendc-experiments-base/build.gradle.kts4
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioHelpers.kt36
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt18
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/Scenario.kt15
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioFactories.kt60
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioReader.kt18
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/CheckpointModelSpec.kt29
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/FailureModelSpec.kt295
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt5
-rw-r--r--opendc-experiments/opendc-experiments-scenario/src/main/resources/scenario.json3
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/CPUPowerModelsFactory.kt9
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java62
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java29
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimWorkloads.java17
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt8
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/FailureColumns.kt40
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/conv/Tables.kt4
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/carbon/CarbonTraceFormat.kt8
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTableReader.kt144
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/FailureTraceFormat.kt88
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureFragment.kt32
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureReadSupport.kt98
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/formats/failure/parquet/FailureRecordMaterializer.kt94
-rw-r--r--opendc-trace/opendc-trace-api/src/main/kotlin/org/opendc/trace/spi/TraceFormat.kt2
-rw-r--r--opendc-web/opendc-web-runner/build.gradle.kts1
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt5
-rw-r--r--settings.gradle.kts6
-rw-r--r--site/docs/documentation/Input/FailureModels.md202
-rw-r--r--site/docs/documentation/Input/Scenario.md4
-rw-r--r--site/docs/documentation/Input/img.pngbin0 -> 110177 bytes
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.
+![img.png](img.png)
+
+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
new file mode 100644
index 00000000..5ad3a85b
--- /dev/null
+++ b/site/docs/documentation/Input/img.png
Binary files differ