Finished cleanup of the server system
This commit is contained in:
@@ -29,7 +29,7 @@ public class ServersController : Controller
|
|||||||
[HttpDelete("{serverId:int}")]
|
[HttpDelete("{serverId:int}")]
|
||||||
public async Task Delete([FromRoute] int serverId)
|
public async Task Delete([FromRoute] int serverId)
|
||||||
{
|
{
|
||||||
//await ServerService.Delete(serverId);
|
await ServerService.Delete(serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{serverId:int}/status")]
|
[HttpGet("{serverId:int}/status")]
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class StorageSubSystem : ServerSubSystem
|
|||||||
AppConfiguration = appConfiguration;
|
AppConfiguration = appConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Initialize()
|
public override Task Initialize()
|
||||||
{
|
{
|
||||||
Logger.LogDebug("Lazy initializing server file system");
|
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);
|
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
|
#region Runtime
|
||||||
@@ -65,7 +73,7 @@ public class StorageSubSystem : ServerSubSystem
|
|||||||
|
|
||||||
if (!Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
|
/*
|
||||||
var consoleSubSystem = Server.GetRequiredSubSystem<ConsoleSubSystem>();
|
var consoleSubSystem = Server.GetRequiredSubSystem<ConsoleSubSystem>();
|
||||||
|
|
||||||
await consoleSubSystem.WriteMoonlight("Creating virtual disk file. Please be patient");
|
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 consoleSubSystem.WriteMoonlight("Mounting virtual disk. Please be patient");
|
||||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||||
|
|
||||||
await consoleSubSystem.WriteMoonlight("Virtual disk ready");
|
await consoleSubSystem.WriteMoonlight("Virtual disk ready");*/
|
||||||
|
|
||||||
// TODO: Implement virtual disk
|
// TODO: Implement virtual disk
|
||||||
}
|
}
|
||||||
@@ -95,6 +103,16 @@ public class StorageSubSystem : ServerSubSystem
|
|||||||
return Task.FromResult(path);
|
return Task.FromResult(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task DeleteRuntimeVolume()
|
||||||
|
{
|
||||||
|
var path = await GetRuntimeHostPath();
|
||||||
|
|
||||||
|
if(!Directory.Exists(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Directory.Delete(path, true);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Installation
|
#region Installation
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Docker.DotNet;
|
|||||||
using Docker.DotNet.Models;
|
using Docker.DotNet.Models;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using MoonCore.Attributes;
|
using MoonCore.Attributes;
|
||||||
|
using MoonCore.Exceptions;
|
||||||
using MoonCore.Models;
|
using MoonCore.Models;
|
||||||
using MoonlightServers.Daemon.Extensions;
|
using MoonlightServers.Daemon.Extensions;
|
||||||
using MoonlightServers.Daemon.Http.Hubs;
|
using MoonlightServers.Daemon.Http.Hubs;
|
||||||
@@ -44,15 +45,10 @@ public class ServerService : IHostedLifecycleService
|
|||||||
|
|
||||||
public async Task Sync(int serverId)
|
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;
|
await Sync(serverId, configuration);
|
||||||
}
|
|
||||||
else
|
|
||||||
await Initialize(serverId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Sync(int serverId, ServerConfiguration configuration)
|
public async Task Sync(int serverId, ServerConfiguration configuration)
|
||||||
@@ -126,7 +122,7 @@ public class ServerService : IHostedLifecycleService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Initialize(configuration);
|
await Sync(configuration.Id, configuration);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -173,6 +169,79 @@ public class ServerService : IHostedLifecycleService
|
|||||||
Servers[configuration.Id] = server;
|
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
|
#region Docker Monitoring
|
||||||
|
|
||||||
private async Task MonitorContainers()
|
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