summaryrefslogtreecommitdiff
path: root/opendc-compute
diff options
context:
space:
mode:
authorDante Niewenhuis <d.niewenhuis@hotmail.com>2024-05-07 12:33:39 +0200
committerGitHub <noreply@github.com>2024-05-07 12:33:39 +0200
commitad20465a5df47b49561bb0afbdda5cd65c5da4b8 (patch)
tree268f0fde5924b71ca2750dbbbba4cbe24c361f12 /opendc-compute
parent7c0691eb6c348d2e49da3ef354b652cf26604905 (diff)
Revamped failure models (#228)
Diffstat (limited to 'opendc-compute')
-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
38 files changed, 1607 insertions, 398 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()
+}