Finished cleanup of the server system
This commit is contained in:
@@ -29,7 +29,7 @@ public class ServersController : Controller
|
||||
[HttpDelete("{serverId:int}")]
|
||||
public async Task Delete([FromRoute] int serverId)
|
||||
{
|
||||
//await ServerService.Delete(serverId);
|
||||
await ServerService.Delete(serverId);
|
||||
}
|
||||
|
||||
[HttpGet("{serverId:int}/status")]
|
||||
|
||||
@@ -21,7 +21,7 @@ public class StorageSubSystem : ServerSubSystem
|
||||
AppConfiguration = appConfiguration;
|
||||
}
|
||||
|
||||
public override async Task Initialize()
|
||||
public override Task Initialize()
|
||||
{
|
||||
Logger.LogDebug("Lazy initializing server file system");
|
||||
|
||||
@@ -42,6 +42,14 @@ public class StorageSubSystem : ServerSubSystem
|
||||
Logger.LogError("An unhandled error occured while lazy initializing server file system: {e}", e);
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task Delete()
|
||||
{
|
||||
await DeleteInstallVolume();
|
||||
await DeleteRuntimeVolume();
|
||||
}
|
||||
|
||||
#region Runtime
|
||||
@@ -65,7 +73,7 @@ public class StorageSubSystem : ServerSubSystem
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
/*
|
||||
var consoleSubSystem = Server.GetRequiredSubSystem<ConsoleSubSystem>();
|
||||
|
||||
await consoleSubSystem.WriteMoonlight("Creating virtual disk file. Please be patient");
|
||||
@@ -77,7 +85,7 @@ public class StorageSubSystem : ServerSubSystem
|
||||
await consoleSubSystem.WriteMoonlight("Mounting virtual disk. Please be patient");
|
||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||
|
||||
await consoleSubSystem.WriteMoonlight("Virtual disk ready");
|
||||
await consoleSubSystem.WriteMoonlight("Virtual disk ready");*/
|
||||
|
||||
// TODO: Implement virtual disk
|
||||
}
|
||||
@@ -95,6 +103,16 @@ public class StorageSubSystem : ServerSubSystem
|
||||
return Task.FromResult(path);
|
||||
}
|
||||
|
||||
private async Task DeleteRuntimeVolume()
|
||||
{
|
||||
var path = await GetRuntimeHostPath();
|
||||
|
||||
if(!Directory.Exists(path))
|
||||
return;
|
||||
|
||||
Directory.Delete(path, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Installation
|
||||
|
||||
@@ -3,6 +3,7 @@ using Docker.DotNet;
|
||||
using Docker.DotNet.Models;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using MoonCore.Attributes;
|
||||
using MoonCore.Exceptions;
|
||||
using MoonCore.Models;
|
||||
using MoonlightServers.Daemon.Extensions;
|
||||
using MoonlightServers.Daemon.Http.Hubs;
|
||||
@@ -44,15 +45,10 @@ public class ServerService : IHostedLifecycleService
|
||||
|
||||
public async Task Sync(int serverId)
|
||||
{
|
||||
if (Servers.TryGetValue(serverId, out var server))
|
||||
{
|
||||
var serverData = await RemoteService.GetServer(serverId);
|
||||
var configuration = serverData.ToServerConfiguration();
|
||||
var serverData = await RemoteService.GetServer(serverId);
|
||||
var configuration = serverData.ToServerConfiguration();
|
||||
|
||||
server.Configuration = configuration;
|
||||
}
|
||||
else
|
||||
await Initialize(serverId);
|
||||
await Sync(serverId, configuration);
|
||||
}
|
||||
|
||||
public async Task Sync(int serverId, ServerConfiguration configuration)
|
||||
@@ -126,7 +122,7 @@ public class ServerService : IHostedLifecycleService
|
||||
{
|
||||
try
|
||||
{
|
||||
await Initialize(configuration);
|
||||
await Sync(configuration.Id, configuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -173,6 +169,79 @@ public class ServerService : IHostedLifecycleService
|
||||
Servers[configuration.Id] = server;
|
||||
}
|
||||
|
||||
public async Task Delete(int serverId)
|
||||
{
|
||||
var server = Find(serverId);
|
||||
|
||||
// If a server with this id doesn't exist we can just exit
|
||||
if (server == null)
|
||||
return;
|
||||
|
||||
if (server.StateMachine.State == ServerState.Installing)
|
||||
throw new HttpApiException("Unable to delete a server while it is installing", 400);
|
||||
|
||||
if (server.StateMachine.State != ServerState.Offline)
|
||||
{
|
||||
// If the server is not offline we need to wait until it goes offline, we
|
||||
// do that by creating the serverOfflineWaiter task completion source which will get triggered
|
||||
// when the event handler for state changes gets informed that the server state is now offline
|
||||
|
||||
var serverOfflineWaiter = new TaskCompletionSource();
|
||||
var timeoutCancellation = new CancellationTokenSource();
|
||||
|
||||
// Set timeout to 10 seconds, this gives the server 10 seconds to go offline, before the request fails
|
||||
timeoutCancellation.CancelAfter(TimeSpan.FromSeconds(10));
|
||||
|
||||
// Subscribe to state updates in order to get notified when the server is offline
|
||||
server.StateMachine.OnTransitioned(transition =>
|
||||
{
|
||||
// Only listen for changes to offline
|
||||
if (transition.Destination != ServerState.Offline)
|
||||
return;
|
||||
|
||||
// If the timeout has already been reached, ignore all changes
|
||||
if (timeoutCancellation.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
// Server is finally offline, notify the request that we now can delete the server
|
||||
serverOfflineWaiter.SetResult();
|
||||
});
|
||||
|
||||
// Now we trigger the kill and waiting for the server to be deleted
|
||||
await server.StateMachine.FireAsync(ServerTrigger.Kill);
|
||||
|
||||
try
|
||||
{
|
||||
await serverOfflineWaiter.Task.WaitAsync(timeoutCancellation.Token);
|
||||
|
||||
await DeleteServer_Unhandled(server);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
Logger.LogWarning(
|
||||
"Deletion of server {id} failed because it didnt stop in time despite being killed",
|
||||
server.Configuration.Id
|
||||
);
|
||||
|
||||
throw new HttpApiException(
|
||||
"Could not kill the server in time for the deletion. Please try again later",
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
await DeleteServer_Unhandled(server);
|
||||
}
|
||||
|
||||
private async Task DeleteServer_Unhandled(Server server)
|
||||
{
|
||||
await server.DisposeAsync();
|
||||
await server.Delete();
|
||||
|
||||
lock (Servers)
|
||||
Servers.Remove(server.Configuration.Id);
|
||||
}
|
||||
|
||||
#region Docker Monitoring
|
||||
|
||||
private async Task MonitorContainers()
|
||||
@@ -283,55 +352,5 @@ public class ServerService : IHostedLifecycleService
|
||||
});
|
||||
*
|
||||
*
|
||||
*public async Task Delete(int serverId)
|
||||
{
|
||||
var server = GetServer(serverId);
|
||||
|
||||
// If a server with this id doesn't exist we can just exit
|
||||
if (server == null)
|
||||
return;
|
||||
|
||||
if (server.State == ServerState.Installing)
|
||||
throw new HttpApiException("Unable to delete a server while it is installing", 400);
|
||||
|
||||
#region Callbacks
|
||||
|
||||
var deleteCompletion = new TaskCompletionSource();
|
||||
|
||||
async Task HandleStateChange(ServerState state)
|
||||
{
|
||||
if (state == ServerState.Offline)
|
||||
await DeleteServer();
|
||||
}
|
||||
|
||||
async Task DeleteServer()
|
||||
{
|
||||
await server.CancelTasks();
|
||||
await server.DestroyStorage();
|
||||
await server.RemoveInstallationVolume();
|
||||
await server.RemoveRuntimeVolume();
|
||||
|
||||
deleteCompletion.SetResult();
|
||||
|
||||
lock (Servers)
|
||||
Servers.Remove(server);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// If the server is still online, we are killing it and then
|
||||
// waiting for the callback to trigger notifying us that the server is now offline
|
||||
// so we can delete it. The request will pause until then using the deleteCompletion task
|
||||
if (server.State != ServerState.Offline)
|
||||
{
|
||||
server.OnStateChanged += HandleStateChange;
|
||||
await server.Kill();
|
||||
|
||||
await deleteCompletion.Task;
|
||||
}
|
||||
else
|
||||
await DeleteServer();
|
||||
}
|
||||
*
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user