diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-03-09 12:57:12 +0100 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-03-09 13:03:20 +0100 |
| commit | 970f5c6f653c8442ecd9b73b208a53a2dbb9a150 (patch) | |
| tree | aa5724ee239cb831e48d45aef8327d7b487e2ad1 /simulator/opendc-compute/opendc-compute-service/src | |
| parent | e97774dbf274fcb57b9d173f9d674a2ef1b982af (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')
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 + } } } |
