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

small code enhancements

parent fedd2491
No related branches found
No related tags found
4 merge requests!159Re-implementation of Theodolite with Kotlin/Quarkus,!157Update Graal Image in CI pipeline,!142Rewrite operator to use k8s states,!83WIP: Re-implementation of Theodolite with Kotlin/Quarkus
Showing
with 86 additions and 48 deletions
......@@ -9,7 +9,7 @@ spec:
kind: benchmark
plural: benchmarks
shortNames:
- bm
- bench
versions:
- name: v1
served: true
......
......@@ -9,7 +9,7 @@ spec:
kind: execution
plural: executions
shortNames:
- ex
- exec
versions:
- name: v1
served: true
......
......@@ -35,7 +35,7 @@ class ClusterSetup(
.list()
.items
.asSequence()
.filter { it.status.executionState == STATES.Running.value }
.filter { it.status.executionState == States.RUNNING.value }
.forEach { execution ->
val benchmark = benchmarkCRDClient
.inNamespace(client.namespace)
......@@ -49,7 +49,7 @@ class ClusterSetup(
Shutdown(execution.spec, benchmark.spec).start()
} else {
logger.error {
"Execution with state ${STATES.Running.value} was found, but no corresponding benchmark. " +
"Execution with state ${States.RUNNING.value} was found, but no corresponding benchmark. " +
"Could not initialize cluster." }
}
......
......@@ -33,9 +33,9 @@ class ExecutionHandler(
logger.info { "Add execution ${execution.metadata.name}" }
execution.spec.name = execution.metadata.name
when (this.stateHandler.getExecutionState(execution.metadata.name)) {
null -> this.stateHandler.setExecutionState(execution.spec.name, STATES.Pending)
STATES.Running -> {
this.stateHandler.setExecutionState(execution.spec.name, STATES.Restart)
null -> this.stateHandler.setExecutionState(execution.spec.name, States.PENDING)
States.RUNNING -> {
this.stateHandler.setExecutionState(execution.spec.name, States.RESTART)
if(this.controller.isExecutionRunning(execution.spec.name)){
this.controller.stop(restart=true)
}
......@@ -58,14 +58,14 @@ class ExecutionHandler(
oldExecution.spec.name = oldExecution.metadata.name
if(gson.toJson(oldExecution.spec) != gson.toJson(newExecution.spec)) {
when(this.stateHandler.getExecutionState(newExecution.metadata.name)) {
STATES.Running -> {
this.stateHandler.setExecutionState(newExecution.spec.name, STATES.Restart)
States.RUNNING -> {
this.stateHandler.setExecutionState(newExecution.spec.name, States.RESTART)
if (this.controller.isExecutionRunning(newExecution.spec.name)){
this.controller.stop(restart=true)
}
}
STATES.Restart -> {} // should this set to pending?
else -> this.stateHandler.setExecutionState(newExecution.spec.name, STATES.Pending)
States.RESTART -> {} // should this set to pending?
else -> this.stateHandler.setExecutionState(newExecution.spec.name, States.PENDING)
}
}
}
......@@ -78,7 +78,7 @@ class ExecutionHandler(
@Synchronized
override fun onDelete(execution: ExecutionCRD, b: Boolean) {
logger.info { "Delete execution ${execution.metadata.name}" }
if(execution.status.executionState == STATES.Running.value
if(execution.status.executionState == States.RUNNING.value
&& this.controller.isExecutionRunning(execution.spec.name)) {
this.controller.stop()
}
......
......@@ -5,7 +5,7 @@ import io.fabric8.kubernetes.client.KubernetesClient
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
import theodolite.model.crd.BenchmarkExecutionList
import theodolite.model.crd.ExecutionCRD
import theodolite.model.crd.STATES
import theodolite.model.crd.States
import java.lang.Thread.sleep
import java.time.Duration
import java.time.Instant
......@@ -33,14 +33,14 @@ class ExecutionStateHandler(context: CustomResourceDefinitionContext, val client
execState
}
fun setExecutionState(resourceName: String, status: STATES): Boolean {
fun setExecutionState(resourceName: String, status: States): Boolean {
setState(resourceName) {cr -> if(cr is ExecutionCRD) cr.status.executionState = status.value; cr}
return blockUntilStateIsSet(resourceName, status.value, getExecutionLambda())
}
fun getExecutionState(resourceName: String) : STATES? {
fun getExecutionState(resourceName: String) : States? {
val status = this.getState(resourceName, getExecutionLambda())
return STATES.values().firstOrNull { it.value == status }
return States.values().firstOrNull { it.value == status }
}
fun setDurationState(resourceName: String, duration: Duration) {
......
package theodolite.execution.operator
import io.fabric8.kubernetes.client.DefaultKubernetesClient
import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderCallbacks
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElectionConfigBuilder
import io.fabric8.kubernetes.client.extended.leaderelection.resourcelock.LeaseLock
import mu.KotlinLogging
import java.time.Duration
import java.util.*
import kotlin.reflect.KFunction0
import kotlin.reflect.KFunction1
private val logger = KotlinLogging.logger {}
class LeaderElector(
val client: NamespacedKubernetesClient,
val name: String
) {
fun getLeadership(leader: KFunction1<NamespacedKubernetesClient, Unit>) {
val lockIdentity: String = UUID.randomUUID().toString()
DefaultKubernetesClient().use { kc ->
kc.leaderElector()
.withConfig(
LeaderElectionConfigBuilder()
.withName("Theodolite")
.withLeaseDuration(Duration.ofSeconds(15L))
.withLock(LeaseLock(client.namespace, name, lockIdentity))
.withRenewDeadline(Duration.ofSeconds(10L))
.withRetryPeriod(Duration.ofSeconds(2L))
.withLeaderCallbacks(LeaderCallbacks(
leader,
{ logger.info { "STOPPED LEADERSHIP " } }
) { newLeader: String? ->
logger.info { "New leader elected $newLeader" }
})
.build()
)
.build().run()
}
}
}
\ No newline at end of file
......@@ -78,23 +78,23 @@ class TheodoliteController(
benchmark.appResource + benchmark.loadGenResource,
execution)
executionStateHandler.setExecutionState(execution.name, STATES.Running)
executionStateHandler.setExecutionState(execution.name, States.RUNNING)
executionStateHandler.startDurationStateTimer(execution.name)
try {
executor = TheodoliteExecutor(execution, benchmark)
executor.run()
when (executionStateHandler.getExecutionState(execution.name)) {
STATES.Restart -> runExecution(execution, benchmark)
STATES.Running -> {
executionStateHandler.setExecutionState(execution.name, STATES.Finished)
States.RESTART -> runExecution(execution, benchmark)
States.RUNNING -> {
executionStateHandler.setExecutionState(execution.name, States.FINISHED)
logger.info { "Execution of ${execution.name} is finally stopped." }
}
}
} catch (e: Exception) {
logger.error { "Failure while executing execution ${execution.name} with benchmark ${benchmark.name}." }
logger.error { "Problem is: $e" }
executionStateHandler.setExecutionState(execution.name, STATES.Failure)
executionStateHandler.setExecutionState(execution.name, States.FAILURE)
}
executionStateHandler.stopDurationStateTimer()
}
......@@ -103,9 +103,9 @@ class TheodoliteController(
fun stop(restart: Boolean = false) {
if (!::executor.isInitialized) return
if (restart) {
executionStateHandler.setExecutionState(this.executor.getExecution().name, STATES.Restart)
executionStateHandler.setExecutionState(this.executor.getExecution().name, States.RESTART)
} else {
executionStateHandler.setExecutionState(this.executor.getExecution().name, STATES.Interrupted)
executionStateHandler.setExecutionState(this.executor.getExecution().name, States.INTERRUPTED)
logger.warn { "Execution ${executor.getExecution().name} unexpected interrupted" }
}
this.executor.executor.run.set(false)
......@@ -129,8 +129,8 @@ class TheodoliteController(
* is selected for the next execution depends on three points:
*
* 1. Only executions are considered for which a matching benchmark is available on the cluster
* 2. The Status of the execution must be [STATES.Pending] or [STATES.Restart]
* 3. Of the remaining [BenchmarkCRD], those with status [STATES.Restart] are preferred,
* 2. The Status of the execution must be [States.PENDING] or [States.RESTART]
* 3. Of the remaining [BenchmarkCRD], those with status [States.RESTART] are preferred,
* then, if there is more than one, the oldest execution is chosen.
*
* @return the next execution or null
......@@ -146,8 +146,8 @@ class TheodoliteController(
.asSequence()
.map { it.spec.name = it.metadata.name; it }
.filter {
it.status.executionState == STATES.Pending.value ||
it.status.executionState == STATES.Restart.value
it.status.executionState == States.PENDING.value ||
it.status.executionState == States.RESTART.value
}
.filter { availableBenchmarkNames.contains(it.spec.benchmark) }
.sortedWith(stateComparator().thenBy { it.metadata.creationTimestamp })
......@@ -157,12 +157,12 @@ class TheodoliteController(
/**
* Simple comparator which can be used to order a list of [ExecutionCRD] such that executions with
* status [STATES.Restart] are before all other executions.
* status [States.RESTART] are before all other executions.
*/
private fun stateComparator() = Comparator<ExecutionCRD> { a, b ->
when {
(a == null && b == null) -> 0
(a.status.executionState == STATES.Restart.value) -> -1
(a.status.executionState == States.RESTART.value) -> -1
else -> 1
}
}
......
......@@ -63,12 +63,6 @@ class K8sManager(private val client: NamespacedKubernetesClient) {
}
}
fun setLabel(resource: KubernetesResource) {
when(resource) {
is Deployment -> this.client
}
}
private fun blockUntilPodsDeleted(podLabel: String) {
while (!this.client.pods().withLabel(podLabel).list().items.isNullOrEmpty()) {
logger.info { "Wait for pods with label '$podLabel' to be deleted." }
......
package theodolite.model.crd
enum class STATES(val value: String) {
Running("RUNNING"),
Pending("PENDING"),
Failure("FAILURE"),
Finished("FINISHED"),
Restart("RESTART"),
Interrupted("INTERRUPTED"),
NoState("NoState")
}
\ No newline at end of file
package theodolite.model.crd
enum class States(val value: String) {
RUNNING("RUNNING"),
PENDING("PENDING"),
FAILURE("FAILURE"),
FINISHED("FINISHED"),
RESTART("RESTART"),
INTERRUPTED("INTERRUPTED"),
NO_STATE("NoState")
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ spec:
kind: benchmark
plural: benchmarks
shortNames:
- bm
- bench
versions:
- name: v1
served: true
......
......@@ -8,7 +8,7 @@ spec:
kind: execution
plural: executions
shortNames:
- ex
- exec
versions:
- name: v1
served: true
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment