summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2022-03-07 22:21:25 +0100
committerFabian Mastenbroek <mail.fabianm@gmail.com>2022-04-04 12:48:04 +0200
commit8f958c5a578dc11b890c96c0dc48e3e3f92a4d07 (patch)
tree698b01cdda347dfed7f9a0e049b780e769adfd77
parentd25d413415b2c429febe14fd2c34d06fd02615b5 (diff)
feat(web/proto): Design unified communication protocol
This change adds a unified communication protocol in form of the module opendc-web-proto which contains the classes that form the communication protocol of OpenDC's API v2. By having the protocol in a separate module, we can utilize the classes in both server and client.
-rw-r--r--buildSrc/build.gradle.kts2
-rw-r--r--gradle/libs.versions.toml7
-rw-r--r--opendc-web/opendc-web-proto/build.gradle.kts39
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt53
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt40
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt34
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt31
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt34
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProtocolError.kt28
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt34
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt33
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt34
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt37
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt36
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt44
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt46
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt43
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt41
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt40
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt40
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt72
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt44
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt43
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt86
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt75
-rw-r--r--settings.gradle.kts1
26 files changed, 1017 insertions, 0 deletions
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 1b24b44b..c2144d00 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -38,4 +38,6 @@ dependencies {
implementation(libs.jmh.gradle)
implementation(libs.dokka.gradle)
implementation(libs.shadow)
+
+ implementation(libs.jandex.gradle)
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a1251a1c..4c52627d 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -6,7 +6,9 @@ commons-math3 = "3.6.1"
dokka = "1.6.10"
hadoop = "3.3.1"
jackson = "2.13.1"
+jandex-gradle = "0.11.0"
jmh-gradle = "0.6.6"
+jakarta-validation = "2.0.2"
junit-jupiter = "5.8.2"
junit-platform = "1.8.2"
kotlin = "1.6.10"
@@ -15,6 +17,7 @@ kotlinx-coroutines = "1.6.0"
ktlint-gradle = "10.2.1"
ktor = "1.6.7"
log4j = "2.17.1"
+microprofile-openapi = "3.0"
mockk = "1.12.2"
opentelemetry-main = "1.11.0"
opentelemetry-metrics = "1.11.0-alpha"
@@ -58,6 +61,7 @@ progressbar = { module = "me.tongfei:progressbar", version.ref = "progressbar" }
# Format
jackson-core = { module = "com.fasterxml.jackson.core:jackson-core", version.ref = "jackson" }
+jackson-annotations = { module = "com.fasterxml.jackson.core:jackson-annotations", version.ref = "jackson" }
jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" }
@@ -73,12 +77,15 @@ ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktor" }
# Other
classgraph = { module = "io.github.classgraph:classgraph", version.ref = "classgraph" }
+jakarta-validation = { module = "jakarta.validation:jakarta.validation-api", version.ref = "jakarta-validation" }
hadoop-common = { module = "org.apache.hadoop:hadoop-common", version.ref = "hadoop" }
hadoop-mapreduce-client-core = { module = "org.apache.hadoop:hadoop-mapreduce-client-core", version.ref = "hadoop" }
commons-math3 = { module = "org.apache.commons:commons-math3", version.ref = "commons-math3" }
+microprofile-openapi-api = { module = "org.eclipse.microprofile.openapi:microprofile-openapi-api", version.ref = "microprofile-openapi" }
# Other (Build)
dokka-gradle = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
+jandex-gradle = { module = "org.kordamp.gradle:jandex-gradle-plugin", version.ref = "jandex-gradle" }
ktlint-gradle = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlint-gradle" }
jmh-gradle = { module = "me.champeau.jmh:jmh-gradle-plugin", version.ref = "jmh-gradle" }
shadow = { module = "gradle.plugin.com.github.johnrengelman:shadow", version.ref = "shadow" }
diff --git a/opendc-web/opendc-web-proto/build.gradle.kts b/opendc-web/opendc-web-proto/build.gradle.kts
new file mode 100644
index 00000000..4a566346
--- /dev/null
+++ b/opendc-web/opendc-web-proto/build.gradle.kts
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+description = "Web communication protocol for OpenDC"
+
+/* Build configuration */
+plugins {
+ `kotlin-library-conventions`
+ id("org.kordamp.gradle.jandex") // Necessary for Quarkus to process annotations
+}
+
+dependencies {
+ implementation(libs.jackson.annotations)
+ implementation(libs.jakarta.validation)
+ implementation(libs.microprofile.openapi.api)
+}
+
+tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
+ kotlinOptions.javaParameters = true
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt
new file mode 100644
index 00000000..38b8ca42
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+/**
+ * State of a scenario for the simulator runner.
+ */
+public enum class JobState {
+ /**
+ * The job is pending to be claimed by a runner.
+ */
+ PENDING,
+
+ /**
+ * The job is claimed by a runner.
+ */
+ CLAIMED,
+
+ /**
+ * The job is currently running.
+ */
+ RUNNING,
+
+ /**
+ * The job has finished.
+ */
+ FINISHED,
+
+ /**
+ * The job has failed.
+ */
+ FAILED;
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt
new file mode 100644
index 00000000..f5c50cc3
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+import com.fasterxml.jackson.annotation.JsonProperty
+
+/**
+ * A machine in a rack.
+ */
+public data class Machine(
+ val id: String,
+ val position: Int,
+ val cpus: List<ProcessingUnit> = emptyList(),
+ val gpus: List<ProcessingUnit> = emptyList(),
+ @JsonProperty("memories")
+ val memory: List<MemoryUnit> = emptyList(),
+ @JsonProperty("storages")
+ val storage: List<MemoryUnit> = emptyList(),
+ val rackId: String? = null
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt
new file mode 100644
index 00000000..1fc604fa
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.web.proto
+
+/**
+ * A memory unit in a system.
+ */
+public data class MemoryUnit(
+ val id: String,
+ val name: String,
+ val speedMbPerS: Double,
+ val sizeMb: Double,
+ val energyConsumptionW: Double
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt
new file mode 100644
index 00000000..f3164f64
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.web.proto
+
+/**
+ * Object describing the enabled operational phenomena for a scenario.
+ */
+public data class OperationalPhenomena(
+ val failures: Boolean,
+ val interference: Boolean
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt
new file mode 100644
index 00000000..5f79d1bd
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.web.proto
+
+/**
+ * A CPU model.
+ */
+public data class ProcessingUnit(
+ val id: String,
+ val name: String,
+ val clockRateMhz: Double,
+ val numberOfCores: Int,
+ val energyConsumptionW: Double
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProtocolError.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProtocolError.kt
new file mode 100644
index 00000000..e7fe2702
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProtocolError.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+/**
+ * Container for reporting errors.
+ */
+public data class ProtocolError(val code: Int, val message: String)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt
new file mode 100644
index 00000000..131aa184
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+/**
+ * A rack in a datacenter.
+ */
+public data class Rack(
+ val id: String,
+ val name: String,
+ val capacity: Int,
+ val powerCapacityW: Double,
+ val machines: List<Machine>
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt
new file mode 100644
index 00000000..5b305168
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+/**
+ * A room in a datacenter.
+ */
+public data class Room(
+ val id: String,
+ val name: String,
+ val tiles: Set<RoomTile>,
+ val topologyId: String? = null,
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt
new file mode 100644
index 00000000..666d66ee
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+/**
+ * A room tile.
+ */
+public data class RoomTile(
+ val id: String,
+ val positionX: Double,
+ val positionY: Double,
+ val rack: Rack? = null,
+ val roomId: String? = null,
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt
new file mode 100644
index 00000000..a0100f72
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+import javax.validation.constraints.Min
+
+/**
+ * The targets of a portfolio.
+ *
+ * @param metrics The selected metrics to track during simulation.
+ * @param repeats The number of repetitions per scenario.
+ */
+public data class Targets(
+ val metrics: Set<String>,
+ @field:Min(1)
+ val repeats: Int = 1
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt
new file mode 100644
index 00000000..2952a273
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto
+
+/**
+ * A workload trace available for simulation.
+ *
+ * @param id The unique identifier of the trace.
+ * @param name The name of the trace.
+ * @param type The type of trace.
+ */
+public data class Trace(
+ val id: String,
+ val name: String,
+ val type: String,
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt
new file mode 100644
index 00000000..cc6e0ed8
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.web.proto
+
+import javax.validation.constraints.DecimalMax
+import javax.validation.constraints.DecimalMin
+
+/**
+ * The workload to simulate for a scenario.
+ */
+public data class Workload(val trace: Trace, val samplingFraction: Double) {
+ /**
+ * Specification for a workload.
+ *
+ * @param trace The unique identifier of the trace.
+ * @param samplingFraction The fraction of the workload to sample.
+ */
+ public data class Spec(
+ val trace: String,
+ @DecimalMin(value = "0.001", message = "Sampling fraction must be non-zero")
+ @DecimalMax(value = "1", message = "Sampling fraction cannot exceed one")
+ val samplingFraction: Double
+ )
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt
new file mode 100644
index 00000000..dfaaa09e
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.runner
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import org.opendc.web.proto.JobState
+import java.time.Instant
+
+/**
+ * A simulation job to be simulated by a runner.
+ */
+@Schema(name = "Runner.Job")
+public data class Job(
+ val id: Long,
+ val scenario: Scenario,
+ val state: JobState,
+ val createdAt: Instant,
+ val updatedAt: Instant,
+ val results: Map<String, Any>? = null
+) {
+ /**
+ * A request to update the state of a job.
+ */
+ @Schema(name = "Runner.Job.Update")
+ public data class Update(val state: JobState, val results: Map<String, Any>? = null)
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt
new file mode 100644
index 00000000..916d8cf0
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.runner
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import org.opendc.web.proto.Targets
+import org.opendc.web.proto.user.Portfolio
+
+/**
+ * A [Portfolio] as seen from the runner's perspective.
+ *
+ * @param id The unique identifier of the portfolio.
+ * @param number The number of the portfolio for the project.
+ * @param name The name of the portfolio.
+ * @param targets The targets of the portfolio.
+ */
+@Schema(name = "Runner.Portfolio")
+public data class Portfolio(
+ val id: Long,
+ val number: Int,
+ val name: String,
+ val targets: Targets,
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt
new file mode 100644
index 00000000..c5e609ec
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.runner
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import org.opendc.web.proto.*
+
+/**
+ * A [Scenario] that is exposed to an OpenDC runner.
+ */
+@Schema(name = "Runner.Scenario")
+public data class Scenario(
+ val id: Long,
+ val number: Int,
+ val portfolio: Portfolio,
+ val name: String,
+ val workload: Workload,
+ val topology: Topology,
+ val phenomena: OperationalPhenomena,
+ val schedulerName: String
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt
new file mode 100644
index 00000000..ea576e71
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.runner
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import org.opendc.web.proto.*
+import java.time.Instant
+
+/**
+ * A [Topology] that is exposed to an OpenDC runner.
+ */
+@Schema(name = "Runner.Topology")
+public data class Topology(
+ val id: Long,
+ val number: Int,
+ val name: String,
+ val rooms: List<Room>,
+ val createdAt: Instant,
+ val updatedAt: Instant,
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt
new file mode 100644
index 00000000..de5f8de3
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.user
+
+import org.opendc.web.proto.JobState
+import org.opendc.web.proto.runner.Job
+import java.time.Instant
+
+/**
+ * A simulation job that is associated with a [Scenario].
+ *
+ * This entity is exposed in the runner-facing API via [Job].
+ */
+public data class Job(
+ val id: Long,
+ val state: JobState,
+ val createdAt: Instant,
+ val updatedAt: Instant,
+ val results: Map<String, Any>? = null
+)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt
new file mode 100644
index 00000000..6f468e79
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.user
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import org.opendc.web.proto.Targets
+import javax.validation.constraints.NotBlank
+
+/**
+ * A portfolio is the composition of multiple scenarios.
+ *
+ * @param id The unique identifier of the portfolio.
+ * @param number The number of the portfolio with respect to the project.
+ * @param project The project to which the portfolio belongs.
+ * @param name The name of the portfolio.
+ * @param targets The targets of the portfolio.
+ * @param scenarios The scenarios in the portfolio.
+ */
+public data class Portfolio(
+ val id: Long,
+ val number: Int,
+ val project: Project,
+ val name: String,
+ val targets: Targets,
+ val scenarios: List<Scenario.Summary>
+) {
+ /**
+ * A request to create a new portfolio.
+ */
+ @Schema(name = "Portfolio.Update")
+ public data class Create(
+ @field:NotBlank(message = "Name must not be empty")
+ val name: String,
+ val targets: Targets
+ )
+
+ /**
+ * A summary view of a [Portfolio] provided for nested relations.
+ *
+ * @param id The unique identifier of the portfolio.
+ * @param number The number of the portfolio for the project.
+ * @param name The name of the portfolio.
+ * @param targets The targets of the portfolio.
+ */
+ @Schema(name = "Portfolio.Summary")
+ public data class Summary(
+ val id: Long,
+ val number: Int,
+ val name: String,
+ val targets: Targets,
+ )
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt
new file mode 100644
index 00000000..3a2807ca
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.user
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import java.time.Instant
+import javax.validation.constraints.NotBlank
+
+/**
+ * A project in OpenDC encapsulates all the datacenter designs and simulation runs for a set of users.
+ */
+public data class Project(
+ val id: Long,
+ val name: String,
+ val createdAt: Instant,
+ val updatedAt: Instant,
+ val role: ProjectRole
+) {
+ /**
+ * A request to create a new project.
+ */
+ @Schema(name = "Project.Create")
+ public data class Create(@field:NotBlank(message = "Name must not be empty") val name: String)
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt
new file mode 100644
index 00000000..0f6de1fc
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.user
+
+/**
+ * The role of a user in a project.
+ */
+public enum class ProjectRole {
+ /**
+ * The user is allowed to view the project.
+ */
+ VIEWER,
+
+ /**
+ * The user is allowed to edit the project.
+ */
+ EDITOR,
+
+ /**
+ * The user owns the project (so he can delete it).
+ */
+ OWNER,
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt
new file mode 100644
index 00000000..552a4912
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.user
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import org.opendc.web.proto.OperationalPhenomena
+import org.opendc.web.proto.Workload
+import javax.validation.constraints.NotBlank
+
+/**
+ * A single scenario to be explored by the simulator.
+ */
+public data class Scenario(
+ val id: Long,
+ val number: Int,
+ val project: Project,
+ val portfolio: Portfolio.Summary,
+ val name: String,
+ val workload: Workload,
+ val topology: Topology.Summary,
+ val phenomena: OperationalPhenomena,
+ val schedulerName: String,
+ val job: Job
+) {
+ /**
+ * Create a new scenario.
+ *
+ * @param name The name of the scenario.
+ * @param workload The workload specification to use for the scenario.
+ * @param topology The number of the topology to use.
+ * @param phenomena The phenomena to model during simulation.
+ * @param schedulerName The name of the scheduler.
+ */
+ @Schema(name = "Scenario.Create")
+ public data class Create(
+ @field:NotBlank(message = "Name must not be empty")
+ val name: String,
+ val workload: Workload.Spec,
+ val topology: Long,
+ val phenomena: OperationalPhenomena,
+ val schedulerName: String,
+ )
+
+ /**
+ * A summary view of a [Scenario] provided for nested relations.
+ *
+ * @param id The unique identifier of the scenario.
+ * @param number The number of the scenario for the project.
+ * @param name The name of the scenario.
+ * @param workload The workload to be modeled by the scenario.
+ * @param phenomena The phenomena simulated for this scenario.
+ * @param schedulerName The scheduler name to use for the experiment.
+ * @param job The simulation job associated with the scenario.
+ */
+ @Schema(name = "Scenario.Summary")
+ public data class Summary(
+ val id: Long,
+ val number: Int,
+ val name: String,
+ val workload: Workload,
+ val topology: Topology.Summary,
+ val phenomena: OperationalPhenomena,
+ val schedulerName: String,
+ val job: Job
+ )
+}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt
new file mode 100644
index 00000000..a144a2e6
--- /dev/null
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.proto.user
+
+import org.eclipse.microprofile.openapi.annotations.media.Schema
+import org.opendc.web.proto.Room
+import java.time.Instant
+import javax.validation.constraints.NotBlank
+
+/**
+ * Model for an OpenDC topology.
+ */
+public data class Topology(
+ val id: Long,
+ val number: Int,
+ val project: Project,
+ val name: String,
+ val rooms: List<Room>,
+ val createdAt: Instant,
+ val updatedAt: Instant,
+) {
+ /**
+ * Create a new topology for a project.
+ */
+ @Schema(name = "Topology.Create")
+ public data class Create(
+ @field:NotBlank(message = "Name must not be empty")
+ val name: String,
+ val rooms: List<Room>
+ )
+
+ /**
+ * Update an existing topology.
+ */
+ @Schema(name = "Topology.Update")
+ public data class Update(val rooms: List<Room>)
+
+ /**
+ * A summary view of a [Topology] provided for nested relations.
+ *
+ * @param id The unique identifier of the topology.
+ * @param number The number of the topology for the project.
+ * @param name The name of the topology.
+ * @param createdAt The instant at which the topology was created.
+ * @param updatedAt The instant at which the topology was updated.
+ */
+ @Schema(name = "Topology.Summary")
+ public data class Summary(
+ val id: Long,
+ val number: Int,
+ val name: String,
+ val createdAt: Instant,
+ val updatedAt: Instant,
+ )
+}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 73275387..d2af9d3a 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -35,6 +35,7 @@ include(":opendc-faas:opendc-faas-simulator")
include(":opendc-experiments:opendc-experiments-capelin")
include(":opendc-experiments:opendc-experiments-serverless20")
include(":opendc-experiments:opendc-experiments-tf20")
+include(":opendc-web:opendc-web-proto")
include(":opendc-web:opendc-web-api")
include(":opendc-web:opendc-web-ui")
include(":opendc-web:opendc-web-runner")