From 82f8418f49b0564c5093c28be1ca522a628d0b4f Mon Sep 17 00:00:00 2001 From: mjkwiatkowski Date: Thu, 26 Feb 2026 19:51:57 +0100 Subject: feat: added notes from last meeting with my supervisor --- dante.txt | 20 ++++++ opendc-common/build.gradle.kts | 1 - .../org/opendc/common/annotations/Endpoint.kt | 6 ++ .../org/opendc/common/annotations/InternalUse.kt | 2 + .../org/opendc/common/api/AssetsController.kt | 72 ++++++++++++++++++++++ .../org/opendc/common/api/ResourceController.kt | 30 +++++++++ .../kotlin/org/opendc/common/utils/HTTPClient.kt | 30 ++++----- .../org/opendc/common/utils/JavalinRunner.kt | 41 ++++-------- .../main/kotlin/org/opendc/common/utils/Kafka.kt | 5 +- .../main/kotlin/org/opendc/common/utils/Redis.kt | 1 - opendc-common/src/main/resources/producer.toml | 2 +- opendc-demo/build.gradle.kts | 4 ++ .../src/main/kotlin/org/opendc/demo/RunRequest.kt | 27 -------- .../experiments/base/runner/ExperimentCli.kt | 2 - .../experiments/base/runner/ExperimentListener.kt | 19 ++++++ .../experiments/base/runner/ExperimentRunner.kt | 18 ------ output/plot-data/file.dat | 5 ++ 17 files changed, 185 insertions(+), 100 deletions(-) create mode 100644 dante.txt create mode 100644 opendc-common/src/main/kotlin/org/opendc/common/annotations/Endpoint.kt create mode 100644 opendc-common/src/main/kotlin/org/opendc/common/api/AssetsController.kt create mode 100644 opendc-common/src/main/kotlin/org/opendc/common/api/ResourceController.kt delete mode 100644 opendc-demo/src/main/kotlin/org/opendc/demo/RunRequest.kt create mode 100644 opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentListener.kt create mode 100644 output/plot-data/file.dat diff --git a/dante.txt b/dante.txt new file mode 100644 index 00000000..6c55eb39 --- /dev/null +++ b/dante.txt @@ -0,0 +1,20 @@ +Create a model in draw.io +Look at OpenTelemetry (read up - is this a lot of work?) +https://github.com/atlarge-research/opendc/tree/radice-paper +Make sure you the fields you specify in the schema itself are automatically exported. +Measure Kafka latency of exporting. +Also ensure whether the user wants to export to database or not. +Add multiple export functions. +Make sure specify the config files in the command line. +The prediction should be about auto-scaling. +BUT -> there is no auto-scaling. +Do auto-scaling. +Idle power takes a lot of energy. +Predicting when to turn nodes on and off would be nice. +Datacenters are heavily underutilized. +Predict when to turn the hosts on and when to turn them off. +Look at the failure models and how they work in OpenDC - this is how I stop a host, and this is how I start back a host. +With auto-scaling you can do it a bit smarter or not. +Do auto-scaling in OpenDC. +Rescheduling. + diff --git a/opendc-common/build.gradle.kts b/opendc-common/build.gradle.kts index dc323140..5838d2d4 100644 --- a/opendc-common/build.gradle.kts +++ b/opendc-common/build.gradle.kts @@ -70,7 +70,6 @@ dependencies { // Source: https://mvnrepository.com/artifact/redis.clients/jedis implementation("redis.clients:jedis:7.3.0") - } diff --git a/opendc-common/src/main/kotlin/org/opendc/common/annotations/Endpoint.kt b/opendc-common/src/main/kotlin/org/opendc/common/annotations/Endpoint.kt new file mode 100644 index 00000000..4ef08a71 --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/annotations/Endpoint.kt @@ -0,0 +1,6 @@ +package org.opendc.common.annotations + +@RequiresOptIn(message = "This is a registered API endpoint.") +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR) +public annotation class Endpoint(val method: String, val name : String) \ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/annotations/InternalUse.kt b/opendc-common/src/main/kotlin/org/opendc/common/annotations/InternalUse.kt index e32aa811..0a57aae9 100644 --- a/opendc-common/src/main/kotlin/org/opendc/common/annotations/InternalUse.kt +++ b/opendc-common/src/main/kotlin/org/opendc/common/annotations/InternalUse.kt @@ -26,3 +26,5 @@ package org.opendc.common.annotations @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR) public annotation class InternalUse + + diff --git a/opendc-common/src/main/kotlin/org/opendc/common/api/AssetsController.kt b/opendc-common/src/main/kotlin/org/opendc/common/api/AssetsController.kt new file mode 100644 index 00000000..c6f34d19 --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/api/AssetsController.kt @@ -0,0 +1,72 @@ +package org.opendc.common.api + +import org.opendc.common.annotations.Endpoint +import io.javalin.http.Handler + +/** + * This class represents the `/assets` endpoint. + * + * @author Mateusz Kwiatkowski + * + * */ + + +//TODO: fix -> this is all wrong. +// Sending the experiment file is completely useless. +// You need to send tasks.parquet +public class AssetsController { + /** + * Returns a concatenated JSON string of all assets. + */ + @Endpoint("GET","/assets") + public fun getAssets() : Handler { + return Handler { ctx -> ctx.status(200) + println(ctx.body()) + } + } + + /** + * Returns an asset with `id` as a JSON string. + */ + @Endpoint("GET", "/assets/{id}") + public fun getAssetsId(): Handler { + return Handler { ctx -> ctx.status(200) } + } + + /** + * Saves the asset specified in the HTTP body. + * Returns the asset `id`. + */ + @Endpoint("POST", "/assets") + public fun postAsset() : Handler { + return Handler { ctx -> ctx.status(200) + println(ctx.body()) + } + } + + /** + * Modifies the specified asset. + * Deletes all results from experiments with this asset. + */ + @Endpoint("PUT", "/assets/{id}") + public fun putAssetId() : Handler { + return Handler { ctx -> ctx.status(200) } + } + + /** + * Deletes an asset with `id`. + * Deletes all results from experiments with this asset. + */ + @Endpoint("DELETE", "/assets/{id}") + public fun deleteAssetId() : Handler { + return Handler { ctx -> ctx.status(200) } + } + + /** + * Deletes all assets + */ + @Endpoint("DELETE", "/assets") + public fun deleteAsset() : Handler { + return Handler { ctx -> ctx.status(200) } + } +} \ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/api/ResourceController.kt b/opendc-common/src/main/kotlin/org/opendc/common/api/ResourceController.kt new file mode 100644 index 00000000..cf1d3cac --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/api/ResourceController.kt @@ -0,0 +1,30 @@ +package org.opendc.common.api + +import org.opendc.common.annotations.Endpoint + +/** + * This class represents the `/resources` endpoint. + * + * @author Mateusz Kwiatkowski + * + * */ + +public class ResourceController { + + /** + * Returns all data analytics for all experiments. + */ + @Endpoint("GET", "/resources") + public fun getResources() { + return + } + + /** + * Returns data analytics for experiment with `id`. + * + * */ + @Endpoint("GET", "/resources") + public fun getResourcesId() { + return + } +} \ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/HTTPClient.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/HTTPClient.kt index cc89d48f..fc5bc57b 100644 --- a/opendc-common/src/main/kotlin/org/opendc/common/utils/HTTPClient.kt +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/HTTPClient.kt @@ -1,35 +1,25 @@ package org.opendc.common.utils import java.io.File +import java.io.InputStreamReader import java.net.URI import java.net.http.* import java.net.http.HttpResponse.BodyHandlers.ofString + /** * Singleton class representing the real datacenter client. * The client is asynchronous and initiates the connection first. * - * @constructor Initiates the connection. - * * @author Mateusz Kwiatkowski */ public class HTTPClient private constructor() { public companion object { private var instance: HTTPClient? = null - private var client: HttpClient? = null - private var handshake = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:8080/")) - .build() + private var client = HttpClient.newBuilder().build() public fun getInstance(): HTTPClient? { if (instance == null) { - try { - client = HttpClient.newBuilder().build() - val response = client?.send(handshake, ofString()) - check(response?.statusCode() == 200) - } catch (e: IllegalStateException) { - println("${e.message}") - } instance = HTTPClient() } return instance @@ -38,13 +28,19 @@ public class HTTPClient private constructor() { // TODO: this class must send the experiment JSON file to the digital twin public fun sendExperiment(experiment: File) { - val body : HttpRequest.BodyPublisher + val input = experiment.inputStream() + val charArray = CharArray(experiment.length().toInt()) + val isr = InputStreamReader(input) + + isr.read(charArray) + val request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:8080/")) + .uri(URI.create("http://localhost:8080/assets")) .header("Content-type", "application/json") // TODO: this is obviously wrong, find an efficient way to send JSON over network - .POST(HttpRequest.BodyPublishers.ofString(experiment)) + .POST(HttpRequest.BodyPublishers.ofString(String(charArray))) .build() - println("Haha") + val response = client?.send(request, ofString()) + check(response?.statusCode() == 200) } } \ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/JavalinRunner.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/JavalinRunner.kt index a43e23a8..23baac27 100644 --- a/opendc-common/src/main/kotlin/org/opendc/common/utils/JavalinRunner.kt +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/JavalinRunner.kt @@ -1,50 +1,33 @@ package org.opendc.common.utils import io.javalin.Javalin -import io.javalin.http.Handler +import org.opendc.common.annotations.Endpoint +import org.opendc.common.api.AssetsController /** * Represents the digital twin monitoring server. + * For endpoint documentation see `AssetsController`. * @author Mateusz Kwiatkowski * @see https://javalin.io/documentation + * @see org.opendc.common.api.AssetsController */ +@OptIn(Endpoint::class) public class JavalinRunner { - private val handshake: Handler = Handler { ctx -> ctx.status(200) } - - private val scenario: Handler = Handler { ctx -> - } + private val assetsController : AssetsController = AssetsController() init { - // Make a CRUD RESTful API - // Specify server config val app = Javalin.create().start() + app.get("/assets", assetsController.getAssets()) - // returns a list of all experiments - app.get("/experiment", handshake) - - // returns a specific experiment - app.get("/experiment/:id", handshake) - - // you need another endpoint for the metrics - - // get the results for the metrics evaluation - app.get("/results/:id", handshake) - - // returns all results - app.get("/results", handshake) + app.get("/assets/{id}", assetsController.getAssetsId()) - // sends a specific experiment - app.post("/experiment", scenario) + app.post("/assets", assetsController.postAsset()) - // changes a specific experiment - app.put("/experiment/:id", scenario) - // this should delete metrics associated with the experiment + app.put("/assets/{id}", assetsController.putAssetId()) - // deletes an experiment with id - app.delete("/experiment/:id", scenario) + app.delete("/assets/{id}", assetsController.deleteAssetId()) - // deletes all experiments - app.delete("/experiment", scenario) + app.delete("/assets", assetsController.deleteAsset()) } } \ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/Kafka.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/Kafka.kt index 1430898e..81eb6752 100644 --- a/opendc-common/src/main/kotlin/org/opendc/common/utils/Kafka.kt +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/Kafka.kt @@ -1,13 +1,10 @@ package org.opendc.common.utils import com.fasterxml.jackson.dataformat.toml.TomlMapper -import org.apache.kafka.clients.consumer.KafkaConsumer import org.apache.kafka.clients.producer.KafkaProducer import org.apache.kafka.clients.producer.ProducerRecord import org.opendc.common.ProtobufMetrics import java.util.* -import kotlin.time.Duration.Companion.microseconds -import kotlin.time.toJavaDuration /** * Represents the Kafka interface. * @constructor `topic` the Kafka topic @@ -34,7 +31,7 @@ public class Kafka(private val topic: String) { try { producer.send(ProducerRecord(this.topic, value)) } catch (e: Exception) { - println("${e.message}") + println("${e.message}") } } } diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/Redis.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/Redis.kt index 67547778..b659d40a 100644 --- a/opendc-common/src/main/kotlin/org/opendc/common/utils/Redis.kt +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/Redis.kt @@ -40,5 +40,4 @@ public class Redis { println(res5) jedis.close() } - } \ No newline at end of file diff --git a/opendc-common/src/main/resources/producer.toml b/opendc-common/src/main/resources/producer.toml index 33a09284..8202e93b 100644 --- a/opendc-common/src/main/resources/producer.toml +++ b/opendc-common/src/main/resources/producer.toml @@ -2,4 +2,4 @@ "key.serializer" = "org.apache.kafka.common.serialization.VoidSerializer" "value.serializer" = "io.confluent.kafka.serializers.protobuf.KafkaProtobufSerializer" "schema.registry.url" = "http://localhost:8081" -"auto.register.schemas" = "true" \ No newline at end of file +"auto.register.schemas" = "true" diff --git a/opendc-demo/build.gradle.kts b/opendc-demo/build.gradle.kts index 7512211a..86ede9c9 100644 --- a/opendc-demo/build.gradle.kts +++ b/opendc-demo/build.gradle.kts @@ -32,3 +32,7 @@ repositories { mavenCentral() maven(url = "https://packages.confluent.io/maven/") } + +dependencies{ + implementation("io.javalin:javalin:6.7.0") +} \ No newline at end of file diff --git a/opendc-demo/src/main/kotlin/org/opendc/demo/RunRequest.kt b/opendc-demo/src/main/kotlin/org/opendc/demo/RunRequest.kt deleted file mode 100644 index c4dfb7ca..00000000 --- a/opendc-demo/src/main/kotlin/org/opendc/demo/RunRequest.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.demo - -public fun runRequest(request: String) { - println("The request is $request\n") -} diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentCli.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentCli.kt index ad662f25..e3b57cb4 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentCli.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentCli.kt @@ -51,11 +51,9 @@ internal class ExperimentCommand : CliktCommand(name = "experiment") { val experiment = getExperiment(experimentPath) HTTPClient.getInstance()?.sendExperiment(experimentPath) runExperiment(experiment) - } catch (e: IOException) { println("${e.message}") } - } } /** diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentListener.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentListener.kt new file mode 100644 index 00000000..de759c0f --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentListener.kt @@ -0,0 +1,19 @@ +package org.opendc.experiments.base.runner + +import org.opendc.common.utils.JavalinRunner +import org.opendc.common.utils.PostgresqlDB +import org.opendc.common.utils.Redis + +/** + * Established a connection with PostgreSQL. + * Creates a Javalin HTTP server and listens for requests. + * + * @author Mateusz Kwiatkowski + * + * @see https://javalin.io/documentation + */ +public fun runListener() { + PostgresqlDB() + Redis().run() + JavalinRunner() +} \ No newline at end of file diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentRunner.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentRunner.kt index 8eab48e6..079db6fc 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentRunner.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentRunner.kt @@ -24,9 +24,6 @@ package org.opendc.experiments.base.runner import me.tongfei.progressbar.ProgressBarBuilder import me.tongfei.progressbar.ProgressBarStyle -import org.opendc.common.utils.JavalinRunner -import org.opendc.common.utils.PostgresqlDB -import org.opendc.common.utils.Redis import org.opendc.experiments.base.experiment.Scenario /** @@ -61,18 +58,3 @@ public fun runExperiment(experiment: List) { } pb.close() } - -/** - * Established a connection with PostgreSQL. - * Creates a Javalin HTTP server and listens for requests. - * - * @author Mateusz Kwiatkowski - * - * @see https://javalin.io/documentation - */ -public fun runListener() { - PostgresqlDB() - JavalinRunner() - Redis().run() - println("Hello world, this means that Javalin already runs on another thread.") -} \ No newline at end of file diff --git a/output/plot-data/file.dat b/output/plot-data/file.dat new file mode 100644 index 00000000..bc5f4069 --- /dev/null +++ b/output/plot-data/file.dat @@ -0,0 +1,5 @@ +x y +1 5 +2 6 +3 7 +4 8 -- cgit v1.2.3