summaryrefslogtreecommitdiff
path: root/simulator/opendc-core/src/main
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2020-10-01 00:49:53 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2020-10-01 10:19:13 +0200
commit8a9f5573bef3f68316add17c04a47cc4e5fe75fa (patch)
tree8dff00c904d5db65e9baf0e7ca2d18a8a61800c1 /simulator/opendc-core/src/main
parent27ddd462d148d70760e45f967387905054e21d20 (diff)
Move OpenDC modules into simulator root
This change moves the OpenDC modules previously living in the simulator/opendc directory to the simulator directory itself given that we do not make a distinction between OpenDC and odcsim anymore.
Diffstat (limited to 'simulator/opendc-core/src/main')
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Environment.kt36
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Identity.kt42
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Platform.kt36
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/User.kt35
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Zone.kt48
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/CorrelatedFaultInjector.kt131
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FailureDomain.kt47
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FaultInjector.kt35
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/UncorrelatedFaultInjector.kt63
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/PowerModel.kt32
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/Powerable.kt37
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/Resource.kt37
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/TagContainer.kt36
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceKey.kt47
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistry.kt63
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistryImpl.kt44
-rw-r--r--simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/workload/Workload.kt39
17 files changed, 808 insertions, 0 deletions
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Environment.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Environment.kt
new file mode 100644
index 00000000..62309bf9
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Environment.kt
@@ -0,0 +1,36 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 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 com.atlarge.opendc.core
+
+/**
+ * A description of a large-scale computing environment. This description includes including key size and topology
+ * information of the environment, types of resources, but also various operational and management rules such as
+ * scheduled maintenance, allocation and other constraints.
+ *
+ * @property name The name of the environment.
+ * @property description A small textual description about the environment that is being modeled.
+ * @property platforms The cloud platforms (such as AWS or GCE) in this environment.
+ */
+data class Environment(val name: String, val description: String?, val platforms: List<Platform>)
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Identity.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Identity.kt
new file mode 100644
index 00000000..c87e934f
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Identity.kt
@@ -0,0 +1,42 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 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 com.atlarge.opendc.core
+
+import java.util.UUID
+
+/**
+ * An object that has a unique identity.
+ */
+interface Identity {
+ /**
+ * A unique, opaque, system-generated value, representing the object.
+ */
+ val uid: UUID
+
+ /**
+ * A non-empty, human-readable string representing the object.
+ */
+ val name: String
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Platform.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Platform.kt
new file mode 100644
index 00000000..0b2437c6
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Platform.kt
@@ -0,0 +1,36 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 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 com.atlarge.opendc.core
+
+import java.util.UUID
+
+/**
+ * A representation of a cloud platform such as Amazon Web Services (AWS), Microsoft Azure or Google Cloud.
+ *
+ * @property uid The unique identifier of this topology.
+ * @property name the name of the platform.
+ * @property zones The availability zones available on this platform.
+ */
+data class Platform(override val uid: UUID, override val name: String, val zones: List<Zone>) : Identity
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/User.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/User.kt
new file mode 100644
index 00000000..6105ae9e
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/User.kt
@@ -0,0 +1,35 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 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 com.atlarge.opendc.core
+
+/**
+ * A user of the cloud network.
+ */
+interface User : Identity {
+ /**
+ * The name of the user.
+ */
+ override val name: String
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Zone.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Zone.kt
new file mode 100644
index 00000000..d8851bcd
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/Zone.kt
@@ -0,0 +1,48 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core
+
+import com.atlarge.opendc.core.services.ServiceRegistry
+import java.util.UUID
+
+/**
+ * An isolated location within a topology region from which public cloud services operate, roughly equivalent to a
+ * single topology. Zones contain one or more clusters and secondary storage.
+ *
+ * This class models *only* the static information of a zone, with dynamic information being contained within the zone's
+ * actor. During runtime, it's actor acts as a registry for all the cloud services provided by the zone.
+ *
+ * @property uid The unique identifier of this availability zone.
+ * @property name The name of the zone within its platform.
+ * @property services The service registry containing the services of the zone.
+ */
+data class Zone(
+ override val uid: UUID,
+ override val name: String,
+ val services: ServiceRegistry
+) : Identity {
+ override fun equals(other: Any?): Boolean = other is Zone && uid == other.uid
+ override fun hashCode(): Int = uid.hashCode()
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/CorrelatedFaultInjector.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/CorrelatedFaultInjector.kt
new file mode 100644
index 00000000..87d6b7bd
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/CorrelatedFaultInjector.kt
@@ -0,0 +1,131 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.failure
+
+import kotlinx.coroutines.*
+import java.time.Clock
+import kotlin.math.exp
+import kotlin.math.max
+import kotlin.random.Random
+import kotlin.random.asJavaRandom
+
+/**
+ * A [FaultInjector] that injects fault in the system which are correlated to each other. Failures do not occur in
+ * isolation, but will trigger other faults.
+ */
+public class CorrelatedFaultInjector(
+ private val coroutineScope: CoroutineScope,
+ private val clock: Clock,
+ private val iatScale: Double,
+ private val iatShape: Double,
+ private val sizeScale: Double,
+ private val sizeShape: Double,
+ private val dScale: Double,
+ private val dShape: Double,
+ random: Random = Random(0)
+) : FaultInjector {
+ /**
+ * The active failure domains that have been registered.
+ */
+ private val active = mutableSetOf<FailureDomain>()
+
+ /**
+ * The [Job] that awaits the nearest fault in the system.
+ */
+ private var job: Job? = null
+
+ /**
+ * The [Random] instance to use.
+ */
+ private val random: java.util.Random = random.asJavaRandom()
+
+ /**
+ * Enqueue the specified [FailureDomain] to fail some time in the future.
+ */
+ override fun enqueue(domain: FailureDomain) {
+ active += domain
+
+ // Clean up the domain if it finishes
+ domain.scope.coroutineContext[Job]!!.invokeOnCompletion {
+ this@CorrelatedFaultInjector.coroutineScope.launch {
+ active -= domain
+
+ if (active.isEmpty()) {
+ job?.cancel()
+ job = null
+ }
+ }
+ }
+
+ if (job != null) {
+ return
+ }
+
+ job = this.coroutineScope.launch {
+ while (active.isNotEmpty()) {
+ ensureActive()
+
+ // Make sure to convert delay from hours to milliseconds
+ val d = lognvariate(iatScale, iatShape) * 3.6e6
+
+ // Handle long overflow
+ if (clock.millis() + d <= 0) {
+ return@launch
+ }
+
+ delay(d.toLong())
+
+ val n = lognvariate(sizeScale, sizeShape).toInt()
+ val targets = active.shuffled(random).take(n)
+
+ for (failureDomain in targets) {
+ active -= failureDomain
+ failureDomain.fail()
+ }
+
+ val df = max(lognvariate(dScale, dShape) * 6e4, 15 * 6e4)
+
+ // Handle long overflow
+ if (clock.millis() + df <= 0) {
+ return@launch
+ }
+
+ delay(df.toLong())
+
+ for (failureDomain in targets) {
+ failureDomain.recover()
+
+ // Re-enqueue machine to be failed
+ enqueue(failureDomain)
+ }
+ }
+
+ job = null
+ }
+ }
+
+ // XXX We should extract this in some common package later on.
+ private fun lognvariate(scale: Double, shape: Double) = exp(scale + shape * random.nextGaussian())
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FailureDomain.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FailureDomain.kt
new file mode 100644
index 00000000..d56df3c9
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FailureDomain.kt
@@ -0,0 +1,47 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.failure
+
+import kotlinx.coroutines.CoroutineScope
+
+/**
+ * A logical or physical component in a computing environment which may fail.
+ */
+public interface FailureDomain {
+ /**
+ * The lifecycle of the failure domain to which a [FaultInjector] will attach.
+ */
+ public val scope: CoroutineScope
+
+ /**
+ * Fail the domain externally.
+ */
+ public suspend fun fail()
+
+ /**
+ * Resume the failure domain.
+ */
+ public suspend fun recover()
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FaultInjector.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FaultInjector.kt
new file mode 100644
index 00000000..ac7a08de
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/FaultInjector.kt
@@ -0,0 +1,35 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.failure
+
+/**
+ * An interface for stochastically injecting faults into a running system.
+ */
+public interface FaultInjector {
+ /**
+ * Enqueue the specified [FailureDomain] into the queue as candidate for failure injection in the future.
+ */
+ public fun enqueue(domain: FailureDomain)
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/UncorrelatedFaultInjector.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/UncorrelatedFaultInjector.kt
new file mode 100644
index 00000000..e96974f7
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/failure/UncorrelatedFaultInjector.kt
@@ -0,0 +1,63 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.failure
+
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import java.time.Clock
+import kotlin.math.ln1p
+import kotlin.math.pow
+import kotlin.random.Random
+
+/**
+ * A [FaultInjector] that injects uncorrelated faults into the system, meaning that failures of the subsystems are
+ * independent.
+ */
+class UncorrelatedFaultInjector(
+ private val clock: Clock,
+ private val alpha: Double,
+ private val beta: Double,
+ private val random: Random = Random(0)
+) : FaultInjector {
+ /**
+ * Enqueue the specified [FailureDomain] to fail some time in the future.
+ */
+ override fun enqueue(domain: FailureDomain) {
+ domain.scope.launch {
+ val d = random.weibull(alpha, beta) * 1e3 // Make sure to convert delay to milliseconds
+
+ // Handle long overflow
+ if (clock.millis() + d <= 0) {
+ return@launch
+ }
+
+ delay(d.toLong())
+ domain.fail()
+ }
+ }
+
+ // XXX We should extract this in some common package later on.
+ private fun Random.weibull(alpha: Double, beta: Double) = (beta * (-ln1p(-nextDouble())).pow(1.0 / alpha))
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/PowerModel.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/PowerModel.kt
new file mode 100644
index 00000000..51c9f379
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/PowerModel.kt
@@ -0,0 +1,32 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.power
+
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * A model for computing the power draw based on some value.
+ */
+public typealias PowerModel<T> = (T) -> Flow<Double>
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/Powerable.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/Powerable.kt
new file mode 100644
index 00000000..4473a571
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/power/Powerable.kt
@@ -0,0 +1,37 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.power
+
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * An entity that is uses power from some power source.
+ */
+public interface Powerable {
+ /**
+ * The power draw at the device's power supply in watts (W).w
+ */
+ val powerDraw: Flow<Double>
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/Resource.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/Resource.kt
new file mode 100644
index 00000000..25a494bc
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/Resource.kt
@@ -0,0 +1,37 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.resource
+
+import com.atlarge.opendc.core.Identity
+
+/**
+ * Represents a generic cloud resource.
+ */
+public interface Resource : Identity {
+ /**
+ * The tags of this cloud resource.
+ */
+ public val tags: TagContainer
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/TagContainer.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/TagContainer.kt
new file mode 100644
index 00000000..6ba1cf0b
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/resource/TagContainer.kt
@@ -0,0 +1,36 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.resource
+
+/**
+ * An immutable map containing the tags of some resource.
+ */
+typealias TagContainer = Map<String, Any>
+
+/**
+ * Obtain the value of the tag with the specified [key] of type [T]. If the tag does not exist or the tag is of
+ * different type, `null` is returned.
+ */
+inline fun <reified T : Any> TagContainer.typed(key: String): T? = this[key] as? T
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceKey.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceKey.kt
new file mode 100644
index 00000000..290bf439
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceKey.kt
@@ -0,0 +1,47 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 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 com.atlarge.opendc.core.services
+
+import com.atlarge.opendc.core.Identity
+import java.util.UUID
+
+/**
+ * An interface for identifying service implementations of the same type (providing the same service).
+ *
+ * @param T The shape of the messages the service responds to.
+ */
+interface ServiceKey<T : Any> : Identity
+
+/**
+ * Helper class for constructing a [ServiceKey].
+ *
+ * @property uid The unique identifier of the service.
+ * @property name The name of the service.
+ */
+abstract class AbstractServiceKey<T : Any>(override val uid: UUID, override val name: String) : ServiceKey<T> {
+ override fun equals(other: Any?): Boolean = other is ServiceKey<*> && uid == other.uid
+ override fun hashCode(): Int = uid.hashCode()
+ override fun toString(): String = "ServiceKey[uid=$uid, name=$name]"
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistry.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistry.kt
new file mode 100644
index 00000000..75aa778f
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistry.kt
@@ -0,0 +1,63 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.services
+
+/**
+ * An immutable service registry interface.
+ */
+public interface ServiceRegistry {
+ /**
+ * The keys in this registry.
+ */
+ public val keys: Collection<ServiceKey<*>>
+
+ /**
+ * Determine if this map contains the service with the specified [ServiceKey].
+ *
+ * @param key The key of the service to check for.
+ * @return `true` if the service is in the map, `false` otherwise.
+ */
+ public operator fun contains(key: ServiceKey<*>): Boolean
+
+ /**
+ * Obtain the service with the specified [ServiceKey].
+ *
+ * @param key The key of the service to obtain.
+ * @return The references to the service.
+ * @throws IllegalArgumentException if the key does not exist in the map.
+ */
+ public operator fun <T : Any> get(key: ServiceKey<T>): T
+
+ /**
+ * Return the result of associating the specified [service] with the given [key] in this registry.
+ */
+ public fun <T : Any> put(key: ServiceKey<T>, service: T): ServiceRegistry
+}
+
+/**
+ * Construct an empty [ServiceRegistry].
+ */
+@Suppress("FunctionName")
+public fun ServiceRegistry(): ServiceRegistry = ServiceRegistryImpl(emptyMap())
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistryImpl.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistryImpl.kt
new file mode 100644
index 00000000..0686ebaf
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/services/ServiceRegistryImpl.kt
@@ -0,0 +1,44 @@
+/*
+ * MIT License
+ *
+ * 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 com.atlarge.opendc.core.services
+
+/**
+ * Default implementation of the [ServiceRegistry] interface.
+ */
+internal class ServiceRegistryImpl(private val map: Map<ServiceKey<*>, Any>) : ServiceRegistry {
+ override val keys: Collection<ServiceKey<*>>
+ get() = map.keys
+
+ override fun contains(key: ServiceKey<*>): Boolean = key in map
+
+ override fun <T : Any> get(key: ServiceKey<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return map[key] as T
+ }
+
+ override fun <T : Any> put(key: ServiceKey<T>, service: T): ServiceRegistry = ServiceRegistryImpl(map.plus(key to service))
+
+ override fun toString(): String = map.toString()
+}
diff --git a/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/workload/Workload.kt b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/workload/Workload.kt
new file mode 100644
index 00000000..def5d6e4
--- /dev/null
+++ b/simulator/opendc-core/src/main/kotlin/com/atlarge/opendc/core/workload/Workload.kt
@@ -0,0 +1,39 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 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 com.atlarge.opendc.core.workload
+
+import com.atlarge.opendc.core.Identity
+import com.atlarge.opendc.core.User
+
+/**
+ * A high-level abstraction that represents the actual work that a set of compute resources perform, such
+ * as running an application on a machine or a whole workflow running multiple tasks on numerous machines.
+ */
+interface Workload : Identity {
+ /**
+ * The owner of this workload.
+ */
+ val owner: User
+}