Skip to content
Snippets Groups Projects
Commit df0812d6 authored by Benedikt Wetzel's avatar Benedikt Wetzel
Browse files

Improve logic of theodolite operator

parent b1bdbfc1
Branches
Tags
4 merge requests!159Re-implementation of Theodolite with Kotlin/Quarkus,!157Update Graal Image in CI pipeline,!106Introduce a Theodolite operator,!83WIP: Re-implementation of Theodolite with Kotlin/Quarkus
This commit is part of merge request !106. Comments created here will be created in the context of that merge request.
...@@ -6,6 +6,8 @@ import io.fabric8.kubernetes.client.informers.SharedInformer ...@@ -6,6 +6,8 @@ import io.fabric8.kubernetes.client.informers.SharedInformer
import mu.KotlinLogging import mu.KotlinLogging
import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.BenchmarkExecution
import theodolite.benchmark.KubernetesBenchmark import theodolite.benchmark.KubernetesBenchmark
import java.util.Queue
import java.util.LinkedList
private val logger = KotlinLogging.logger {} private val logger = KotlinLogging.logger {}
...@@ -15,10 +17,9 @@ class TheodoliteController( ...@@ -15,10 +17,9 @@ class TheodoliteController(
val informerBenchmarkExecution: SharedInformer<BenchmarkExecution>, val informerBenchmarkExecution: SharedInformer<BenchmarkExecution>,
val informerBenchmarkType: SharedInformer<KubernetesBenchmark> val informerBenchmarkType: SharedInformer<KubernetesBenchmark>
) { ) {
var execution: BenchmarkExecution? = null var executor: TheodoliteExecutor = TheodoliteExecutor()
var benchmarkType: KubernetesBenchmark? = null val executionsQueue: Queue<BenchmarkExecution> = LinkedList<BenchmarkExecution>()
var executor: TheodoliteExecutor? = null val benchmarks: MutableMap<String, KubernetesBenchmark> = HashMap()
var updated: Boolean = true
/** /**
* Adds the EventHandler to kubernetes * Adds the EventHandler to kubernetes
...@@ -27,33 +28,48 @@ class TheodoliteController( ...@@ -27,33 +28,48 @@ class TheodoliteController(
informerBenchmarkExecution.addEventHandler(object : ResourceEventHandler<BenchmarkExecution> { informerBenchmarkExecution.addEventHandler(object : ResourceEventHandler<BenchmarkExecution> {
override fun onAdd(benchmarkExecution: BenchmarkExecution) { override fun onAdd(benchmarkExecution: BenchmarkExecution) {
execution = benchmarkExecution executionsQueue.add(benchmarkExecution)
} }
override fun onUpdate(oldExecution: BenchmarkExecution, newExecution: BenchmarkExecution) { override fun onUpdate(oldExecution: BenchmarkExecution, newExecution: BenchmarkExecution) {
execution = newExecution if (executor.getExecution().name == newExecution.name) {
updated = true executor.stop()
shutdown() executor.setExecution(newExecution)
executor.run()
} else {
executionsQueue.remove(oldExecution)
onAdd(newExecution)
}
} }
override fun onDelete(benchmarkExecution: BenchmarkExecution, b: Boolean) { override fun onDelete(execution: BenchmarkExecution, b: Boolean) {
shutdown() if (executor.getExecution().name == execution.name) {
executor.stop()
} else {
executionsQueue.remove(execution)
}
} }
}) })
informerBenchmarkType.addEventHandler(object : ResourceEventHandler<KubernetesBenchmark> { informerBenchmarkType.addEventHandler(object : ResourceEventHandler<KubernetesBenchmark> {
override fun onAdd(kubernetesBenchmark: KubernetesBenchmark) { override fun onAdd(kubernetesBenchmark: KubernetesBenchmark) {
benchmarkType = kubernetesBenchmark benchmarks[kubernetesBenchmark.name] = kubernetesBenchmark
} }
override fun onUpdate(oldBenchmark: KubernetesBenchmark, newBenchmark: KubernetesBenchmark) { override fun onUpdate(oldBenchmark: KubernetesBenchmark, newBenchmark: KubernetesBenchmark) {
benchmarkType = newBenchmark onAdd(newBenchmark)
updated = true if (executor.getBenchmark().name == oldBenchmark.name) {
shutdown() executor.stop()
executor.setBenchmark(newBenchmark)
executor.run()
}
} }
override fun onDelete(kubernetesBenchmark: KubernetesBenchmark, b: Boolean) { override fun onDelete(benchmark: KubernetesBenchmark, b: Boolean) {
shutdown() benchmarks.remove(benchmark.name)
if(executor.getBenchmark().name == benchmark.name) {
executor.stop()
}
} }
}) })
} }
...@@ -70,17 +86,18 @@ class TheodoliteController( ...@@ -70,17 +86,18 @@ class TheodoliteController(
@Synchronized @Synchronized
private fun reconcile() { private fun reconcile() {
val localExecution = this.execution while(executionsQueue.isNotEmpty() && !executor.isRunning) {
val localType = this.benchmarkType val execution = executionsQueue.poll()
val benchmark = benchmarks[execution.name]
if (localType is KubernetesBenchmark && localExecution is BenchmarkExecution && updated) { if (benchmark == null) {
executor = TheodoliteExecutor(config = localExecution, kubernetesBenchmark = localType) logger.error { "No benchmark found for execution ${execution.name}" }
executor!!.run() executionsQueue.add(execution)
updated = false } else {
executor.setExecution(execution)
executor.setBenchmark(benchmark)
executor.run()
} }
} }
private fun shutdown() {
Shutdown(benchmarkExecution = execution!!, benchmark = benchmarkType!!).run()
} }
} }
package theodolite.execution package theodolite.execution
import mu.KotlinLogging
import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.BenchmarkExecution
import theodolite.benchmark.KubernetesBenchmark import theodolite.benchmark.KubernetesBenchmark
import theodolite.patcher.PatcherDefinitionFactory import theodolite.patcher.PatcherDefinitionFactory
...@@ -10,11 +11,29 @@ import theodolite.util.LoadDimension ...@@ -10,11 +11,29 @@ import theodolite.util.LoadDimension
import theodolite.util.Resource import theodolite.util.Resource
import theodolite.util.Results import theodolite.util.Results
import java.time.Duration import java.time.Duration
import kotlin.system.exitProcess
private val logger = KotlinLogging.logger {}
class TheodoliteExecutor( class TheodoliteExecutor(
private val config: BenchmarkExecution, private var config: BenchmarkExecution,
private val kubernetesBenchmark: KubernetesBenchmark private var kubernetesBenchmark: KubernetesBenchmark
) { ) {
private val executionThread = Thread {
if(config == null || kubernetesBenchmark == null) {
logger.error { "Execution or Benchmark not found" }
}else {
val config = buildConfig()
// execute benchmarks for each load
for (load in config.loads) {
config.compositeStrategy.findSuitableResource(load, config.resources)
}
}
}
var isRunning = false
private fun buildConfig(): Config { private fun buildConfig(): Config {
val results = Results() val results = Results()
...@@ -62,12 +81,31 @@ class TheodoliteExecutor( ...@@ -62,12 +81,31 @@ class TheodoliteExecutor(
) )
} }
fun getExecution(): BenchmarkExecution {
return this.config
}
fun getBenchmark(): KubernetesBenchmark {
return this.kubernetesBenchmark
}
fun run() { fun run() {
val config = buildConfig() isRunning = true
executionThread.run()
}
// execute benchmarks for each load fun stop() {
for (load in config.loads) { isRunning = false
config.compositeStrategy.findSuitableResource(load, config.resources) executionThread.interrupt()
}
fun setExecution(config: BenchmarkExecution) {
this.config = config
} }
fun setBenchmark(benchmark: KubernetesBenchmark) {
this.kubernetesBenchmark = benchmark
} }
constructor() {}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment