summaryrefslogtreecommitdiff
path: root/simulator/opendc-compute/opendc-compute-service/src
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-03-09 12:57:12 +0100
committerFabian Mastenbroek <mail.fabianm@gmail.com>2021-03-09 13:03:20 +0100
commit970f5c6f653c8442ecd9b73b208a53a2dbb9a150 (patch)
treeaa5724ee239cb831e48d45aef8327d7b487e2ad1 /simulator/opendc-compute/opendc-compute-service/src
parente97774dbf274fcb57b9d173f9d674a2ef1b982af (diff)
compute: Add lifecycle methods for Server instances
This change adds more methods for controlling the lifecycle of Server instances.
Diffstat (limited to 'simulator/opendc-compute/opendc-compute-service/src')
-rw-r--r--simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt6
-rw-r--r--simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ClientServer.kt15
-rw-r--r--simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ComputeServiceImpl.kt99
3 files changed, 99 insertions, 21 deletions
diff --git a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt
index 060c35fd..c3c39572 100644
--- a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt
+++ b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/driver/Host.kt
@@ -79,7 +79,7 @@ public interface Host {
public operator fun contains(server: Server): Boolean
/**
- * Stat the server [instance][server] if it is currently not running on this host.
+ * Start the server [instance][server] if it is currently not running on this host.
*
* @throws IllegalArgumentException if the server is not present on the host.
*/
@@ -93,9 +93,9 @@ public interface Host {
public suspend fun stop(server: Server)
/**
- * Terminate the specified [instance][server] on this host and cleanup all resources associated with it.
+ * Delete the specified [instance][server] on this host and cleanup all resources associated with it.
*/
- public suspend fun terminate(server: Server)
+ public suspend fun delete(server: Server)
/**
* Add a [HostListener] to this host.
diff --git a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ClientServer.kt b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ClientServer.kt
index f84b7435..e65c5f1c 100644
--- a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ClientServer.kt
+++ b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ClientServer.kt
@@ -52,6 +52,21 @@ internal class ClientServer(private val delegate: Server) : Server, ServerWatche
override var state: ServerState = delegate.state
private set
+ override suspend fun start() {
+ delegate.start()
+ refresh()
+ }
+
+ override suspend fun stop() {
+ delegate.stop()
+ refresh()
+ }
+
+ override suspend fun delete() {
+ delegate.delete()
+ refresh()
+ }
+
override fun watch(watcher: ServerWatcher) {
if (watchers.isEmpty()) {
delegate.watch(this)
diff --git a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ComputeServiceImpl.kt b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ComputeServiceImpl.kt
index 69d6bb59..453f5d65 100644
--- a/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ComputeServiceImpl.kt
+++ b/simulator/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/internal/ComputeServiceImpl.kt
@@ -92,7 +92,7 @@ public class ComputeServiceImpl(
/**
* The active servers in the system.
*/
- private val activeServers: MutableSet<Server> = mutableSetOf()
+ private val activeServers: MutableMap<Server, Host> = mutableMapOf()
public var submittedVms: Int = 0
public var queuedVms: Int = 0
@@ -126,7 +126,12 @@ public class ComputeServiceImpl(
override fun newClient(): ComputeClient = object : ComputeClient {
private var isClosed: Boolean = false
- override suspend fun newServer(name: String, image: Image, flavor: Flavor): Server {
+ override suspend fun newServer(
+ name: String,
+ image: Image,
+ flavor: Flavor,
+ start: Boolean
+ ): Server {
check(!isClosed) { "Client is closed" }
tracer.commit(VmSubmissionEvent(name, image, flavor))
@@ -143,11 +148,12 @@ public class ComputeServiceImpl(
)
)
- return suspendCancellableCoroutine { cont ->
- val request = LaunchRequest(createServer(name, image, flavor), cont)
- queue += request
- requestCycle()
+ val server = createServer(name, image, flavor)
+ if (start) {
+ server.start()
}
+
+ return ClientServer(server)
}
override fun close() {
@@ -186,13 +192,13 @@ public class ComputeServiceImpl(
private fun createServer(
name: String,
image: Image,
- flavor: Flavor
- ): Server {
+ flavor: Flavor,
+ ): ServerImpl {
return ServerImpl(
uid = UUID(random.nextLong(), random.nextLong()),
- name = name,
- flavor = flavor,
- image = image
+ name,
+ flavor,
+ image
)
}
@@ -258,9 +264,9 @@ public class ComputeServiceImpl(
scope.launch {
try {
- cont.resume(ClientServer(server))
selectedHv.host.spawn(server)
- activeServers += server
+ cont.resume(Unit)
+ activeServers[server] = selectedHv.host
tracer.commit(VmScheduledEvent(server.name))
_events.emit(
@@ -348,9 +354,8 @@ public class ComputeServiceImpl(
override fun onStateChanged(host: Host, server: Server, newState: ServerState) {
val serverImpl = server as ServerImpl
serverImpl.state = newState
- serverImpl.watchers.forEach { it.onStateChanged(server, newState) }
- if (newState == ServerState.SHUTOFF) {
+ if (newState == ServerState.TERMINATED || newState == ServerState.DELETED) {
logger.info { "[${clock.millis()}] Server ${server.uid} ${server.name} ${server.flavor} finished." }
tracer.commit(VmStoppedEvent(server.name))
@@ -385,9 +390,9 @@ public class ComputeServiceImpl(
}
}
- public data class LaunchRequest(val server: Server, val cont: Continuation<Server>)
+ private data class LaunchRequest(val server: ServerImpl, val cont: Continuation<Unit>)
- private class ServerImpl(
+ private inner class ServerImpl(
override val uid: UUID,
override val name: String,
override val flavor: Flavor,
@@ -395,6 +400,57 @@ public class ComputeServiceImpl(
) : Server {
val watchers = mutableListOf<ServerWatcher>()
+ override suspend fun start() {
+ when (state) {
+ ServerState.RUNNING -> {
+ logger.debug { "User tried to start server but server is already running" }
+ return
+ }
+ ServerState.PROVISIONING -> {
+ logger.debug { "User tried to start server but request is already pending: doing nothing" }
+ return
+ }
+ ServerState.DELETED -> {
+ logger.warn { "User tried to start terminated server" }
+ throw IllegalArgumentException("Server is terminated")
+ }
+ else -> {
+ logger.info { "User requested to start server $uid" }
+ state = ServerState.PROVISIONING
+ suspendCancellableCoroutine<Unit> { cont ->
+ val request = LaunchRequest(this, cont)
+ queue += request
+ requestCycle()
+ }
+ }
+ }
+ }
+
+ override suspend fun stop() {
+ when (state) {
+ ServerState.PROVISIONING -> {} // TODO Find way to interrupt these
+ ServerState.RUNNING, ServerState.ERROR -> {
+ // Warn: possible race condition on activeServers
+ val host = checkNotNull(activeServers[this]) { "Server not running" }
+ host.stop(this)
+ }
+ ServerState.TERMINATED -> {} // No work needed
+ ServerState.DELETED -> throw IllegalStateException("Server is terminated")
+ }
+ }
+
+ override suspend fun delete() {
+ when (state) {
+ ServerState.PROVISIONING -> {} // TODO Find way to interrupt these
+ ServerState.RUNNING -> {
+ // Warn: possible race condition on activeServers
+ val host = checkNotNull(activeServers[this]) { "Server not running" }
+ host.delete(this)
+ }
+ else -> {} // No work needed
+ }
+ }
+
override fun watch(watcher: ServerWatcher) {
watchers += watcher
}
@@ -409,6 +465,13 @@ public class ComputeServiceImpl(
override val tags: Map<String, String> = emptyMap()
- override var state: ServerState = ServerState.BUILD
+ override var state: ServerState = ServerState.TERMINATED
+ set(value) {
+ if (value != field) {
+ watchers.forEach { it.onStateChanged(this, value) }
+ }
+
+ field = value
+ }
}
}