Added node server sync and delete sync. Cleaned up codebase and extracted calls to apis to services
This commit is contained in:
@@ -22,9 +22,17 @@ public partial class Server
|
||||
|
||||
await LogToConsole("Fetching installation configuration");
|
||||
|
||||
// Fetching remote configuration
|
||||
// Fetching remote configuration and install config
|
||||
var remoteService = ServiceProvider.GetRequiredService<RemoteService>();
|
||||
|
||||
var installData = await remoteService.GetServerInstallation(Configuration.Id);
|
||||
var serverData = await remoteService.GetServer(Configuration.Id);
|
||||
|
||||
// We are updating the regular server config here as well
|
||||
// as changes to variables and other settings wouldn't sync otherwise
|
||||
// because they won't trigger a sync
|
||||
var serverConfiguration = serverData.ToServerConfiguration();
|
||||
UpdateConfiguration(serverConfiguration);
|
||||
|
||||
var dockerImageService = ServiceProvider.GetRequiredService<DockerImageService>();
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Docker.DotNet;
|
||||
using MoonlightServers.Daemon.Enums;
|
||||
using MoonlightServers.Daemon.Extensions;
|
||||
using MoonlightServers.Daemon.Services;
|
||||
|
||||
namespace MoonlightServers.Daemon.Abstractions;
|
||||
|
||||
@@ -11,6 +13,17 @@ public partial class Server
|
||||
{
|
||||
try
|
||||
{
|
||||
await LogToConsole("Fetching configuration");
|
||||
|
||||
var remoteService = ServiceProvider.GetRequiredService<RemoteService>();
|
||||
var serverData = await remoteService.GetServer(Configuration.Id);
|
||||
|
||||
// We are updating the server config here
|
||||
// as changes to variables and other settings wouldn't sync otherwise
|
||||
// because they won't trigger a sync
|
||||
var serverConfiguration = serverData.ToServerConfiguration();
|
||||
UpdateConfiguration(serverConfiguration);
|
||||
|
||||
await ReCreate();
|
||||
|
||||
await LogToConsole("Starting container");
|
||||
|
||||
@@ -49,4 +49,7 @@ public partial class Server
|
||||
RuntimeContainerName = $"moonlight-runtime-{Configuration.Id}";
|
||||
InstallationContainerName = $"moonlight-install-{Configuration.Id}";
|
||||
}
|
||||
|
||||
public void UpdateConfiguration(ServerConfiguration configuration)
|
||||
=> Configuration = configuration;
|
||||
}
|
||||
@@ -2,11 +2,35 @@ using Docker.DotNet.Models;
|
||||
using Mono.Unix.Native;
|
||||
using MoonCore.Helpers;
|
||||
using MoonlightServers.Daemon.Models.Cache;
|
||||
using MoonlightServers.DaemonShared.PanelSide.Http.Responses;
|
||||
|
||||
namespace MoonlightServers.Daemon.Extensions;
|
||||
|
||||
public static class ServerConfigurationExtensions
|
||||
{
|
||||
public static ServerConfiguration ToServerConfiguration(this ServerDataResponse response)
|
||||
{
|
||||
return new ServerConfiguration()
|
||||
{
|
||||
Id = response.Id,
|
||||
StartupCommand = response.StartupCommand,
|
||||
Allocations = response.Allocations.Select(y => new ServerConfiguration.AllocationConfiguration()
|
||||
{
|
||||
IpAddress = y.IpAddress,
|
||||
Port = y.Port
|
||||
}).ToArray(),
|
||||
Variables = response.Variables,
|
||||
OnlineDetection = response.OnlineDetection,
|
||||
DockerImage = response.DockerImage,
|
||||
UseVirtualDisk = response.UseVirtualDisk,
|
||||
Bandwidth = response.Bandwidth,
|
||||
Cpu = response.Cpu,
|
||||
Disk = response.Disk,
|
||||
Memory = response.Memory,
|
||||
StopCommand = response.StopCommand
|
||||
};
|
||||
}
|
||||
|
||||
public static CreateContainerParameters ToRuntimeCreateParameters(this ServerConfiguration configuration,
|
||||
string hostPath, string containerName)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoonCore.Exceptions;
|
||||
using MoonlightServers.Daemon.Enums;
|
||||
@@ -5,6 +6,7 @@ using MoonlightServers.Daemon.Services;
|
||||
|
||||
namespace MoonlightServers.Daemon.Http.Controllers.Servers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/servers")]
|
||||
public class ServerPowerController : Controller
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoonCore.Exceptions;
|
||||
using MoonlightServers.Daemon.Services;
|
||||
@@ -6,6 +7,7 @@ using MoonlightServers.DaemonShared.Enums;
|
||||
|
||||
namespace MoonlightServers.Daemon.Http.Controllers.Servers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/servers")]
|
||||
public class ServersController : Controller
|
||||
@@ -17,18 +19,32 @@ public class ServersController : Controller
|
||||
ServerService = serverService;
|
||||
}
|
||||
|
||||
[HttpPost("{serverId:int}/sync")]
|
||||
public async Task Sync([FromRoute] int serverId)
|
||||
{
|
||||
await ServerService.Sync(serverId);
|
||||
}
|
||||
|
||||
[HttpDelete("{serverId:int}")]
|
||||
public async Task Delete([FromRoute] int serverId)
|
||||
{
|
||||
await ServerService.Delete(serverId);
|
||||
}
|
||||
|
||||
[HttpGet("{serverId:int}/status")]
|
||||
public async Task<ServerStatusResponse> GetStatus(int serverId)
|
||||
public Task<ServerStatusResponse> GetStatus([FromRoute] int serverId)
|
||||
{
|
||||
var server = ServerService.GetServer(serverId);
|
||||
|
||||
if (server == null)
|
||||
throw new HttpApiException("No server with this id found", 404);
|
||||
|
||||
return new ServerStatusResponse()
|
||||
var result = new ServerStatusResponse()
|
||||
{
|
||||
State = (ServerState)server.State
|
||||
};
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
[HttpGet("{serverId:int}/logs")]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoonlightServers.Daemon.Helpers;
|
||||
using MoonlightServers.DaemonShared.DaemonSide.Http.Responses.Statistics;
|
||||
@@ -6,6 +7,7 @@ namespace MoonlightServers.Daemon.Http.Controllers.Statistics;
|
||||
|
||||
// This controller hosts endpoints for the statistics for the daemon application itself
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/statistics/application")]
|
||||
public class StatisticsApplicationController : Controller
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoonlightServers.Daemon.Services;
|
||||
using MoonlightServers.DaemonShared.DaemonSide.Http.Responses.Statistics;
|
||||
@@ -6,6 +7,7 @@ namespace MoonlightServers.Daemon.Http.Controllers.Statistics;
|
||||
|
||||
// This controller hosts endpoints for the statistics for the docker environment
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/statistics/docker")]
|
||||
public class StatisticsDockerController : Controller
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoonlightServers.Daemon.Helpers;
|
||||
using MoonlightServers.DaemonShared.DaemonSide.Http.Responses.Statistics;
|
||||
@@ -6,6 +7,7 @@ namespace MoonlightServers.Daemon.Http.Controllers.Statistics;
|
||||
|
||||
// This controller hosts endpoints for the statistics for host system the daemon runs on
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/statistics/host")]
|
||||
public class StatisticsHostController : Controller
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoonlightServers.Daemon.Services;
|
||||
using MoonlightServers.DaemonShared.DaemonSide.Http.Responses.Sys;
|
||||
|
||||
namespace MoonlightServers.Daemon.Http.Controllers.Sys;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/system/status")]
|
||||
public class SystemStatusController : Controller
|
||||
|
||||
@@ -31,6 +31,13 @@ public class RemoteService
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<ServerDataResponse> GetServer(int serverId)
|
||||
{
|
||||
return await ApiClient.GetJson<ServerDataResponse>(
|
||||
$"api/remote/servers/{serverId}"
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<ServerInstallDataResponse> GetServerInstallation(int serverId)
|
||||
{
|
||||
return await ApiClient.GetJson<ServerInstallDataResponse>(
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Docker.DotNet;
|
||||
using Docker.DotNet.Models;
|
||||
using MoonCore.Attributes;
|
||||
using MoonCore.Exceptions;
|
||||
using MoonCore.Models;
|
||||
using MoonlightServers.Daemon.Abstractions;
|
||||
using MoonlightServers.Daemon.Enums;
|
||||
using MoonlightServers.Daemon.Extensions;
|
||||
using MoonlightServers.Daemon.Models.Cache;
|
||||
using MoonlightServers.DaemonShared.PanelSide.Http.Responses;
|
||||
|
||||
@@ -16,11 +19,15 @@ public class ServerService : IHostedLifecycleService
|
||||
private readonly RemoteService RemoteService;
|
||||
private readonly IServiceProvider ServiceProvider;
|
||||
private readonly ILoggerFactory LoggerFactory;
|
||||
private bool IsInitialized = false;
|
||||
private CancellationTokenSource Cancellation = new();
|
||||
private bool IsInitialized = false;
|
||||
|
||||
public ServerService(RemoteService remoteService, ILogger<ServerService> logger, IServiceProvider serviceProvider,
|
||||
ILoggerFactory loggerFactory)
|
||||
public ServerService(
|
||||
RemoteService remoteService,
|
||||
ILogger<ServerService> logger,
|
||||
IServiceProvider serviceProvider,
|
||||
ILoggerFactory loggerFactory
|
||||
)
|
||||
{
|
||||
RemoteService = remoteService;
|
||||
Logger = logger;
|
||||
@@ -35,8 +42,8 @@ public class ServerService : IHostedLifecycleService
|
||||
Logger.LogWarning("Ignoring initialize call: Already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
IsInitialized = true;
|
||||
else
|
||||
IsInitialized = true;
|
||||
|
||||
// Loading models and converting them
|
||||
Logger.LogInformation("Fetching servers from panel");
|
||||
@@ -45,25 +52,9 @@ public class ServerService : IHostedLifecycleService
|
||||
await RemoteService.GetServers(page, pageSize)
|
||||
);
|
||||
|
||||
var configurations = servers.Select(x => new ServerConfiguration()
|
||||
{
|
||||
Id = x.Id,
|
||||
StartupCommand = x.StartupCommand,
|
||||
Allocations = x.Allocations.Select(y => new ServerConfiguration.AllocationConfiguration()
|
||||
{
|
||||
IpAddress = y.IpAddress,
|
||||
Port = y.Port
|
||||
}).ToArray(),
|
||||
Variables = x.Variables,
|
||||
OnlineDetection = x.OnlineDetection,
|
||||
DockerImage = x.DockerImage,
|
||||
UseVirtualDisk = x.UseVirtualDisk,
|
||||
Bandwidth = x.Bandwidth,
|
||||
Cpu = x.Cpu,
|
||||
Disk = x.Disk,
|
||||
Memory = x.Memory,
|
||||
StopCommand = x.StopCommand
|
||||
}).ToArray();
|
||||
var configurations = servers
|
||||
.Select(x => x.ToServerConfiguration())
|
||||
.ToArray();
|
||||
|
||||
Logger.LogInformation("Initializing {count} servers", servers.Length);
|
||||
|
||||
@@ -91,7 +82,7 @@ public class ServerService : IHostedLifecycleService
|
||||
await Cancellation.CancelAsync();
|
||||
}
|
||||
|
||||
private async Task AttachToDockerEvents()
|
||||
private Task AttachToDockerEvents()
|
||||
{
|
||||
var dockerClient = ServiceProvider.GetRequiredService<DockerClient>();
|
||||
|
||||
@@ -123,11 +114,11 @@ public class ServerService : IHostedLifecycleService
|
||||
await server.NotifyRuntimeContainerDied();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Check if it's an installation container
|
||||
lock (Servers)
|
||||
server = Servers.FirstOrDefault(x => x.InstallationContainerId == message.ID);
|
||||
|
||||
|
||||
if (server != null)
|
||||
{
|
||||
await server.NotifyInstallationContainerDied();
|
||||
@@ -144,9 +135,11 @@ public class ServerService : IHostedLifecycleService
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task InitializeServerRange(ServerConfiguration[] serverConfigurations)
|
||||
public async Task InitializeServerRange(ServerConfiguration[] serverConfigurations)
|
||||
{
|
||||
var dockerClient = ServiceProvider.GetRequiredService<DockerClient>();
|
||||
|
||||
@@ -173,7 +166,7 @@ public class ServerService : IHostedLifecycleService
|
||||
await InitializeServer(configuration, existingContainers);
|
||||
}
|
||||
|
||||
private async Task InitializeServer(
|
||||
public async Task<Server> InitializeServer(
|
||||
ServerConfiguration serverConfiguration,
|
||||
IList<ContainerListResponse> existingContainers
|
||||
)
|
||||
@@ -190,6 +183,70 @@ public class ServerService : IHostedLifecycleService
|
||||
|
||||
lock (Servers)
|
||||
Servers.Add(server);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
public async Task Sync(int serverId)
|
||||
{
|
||||
var serverData = await RemoteService.GetServer(serverId);
|
||||
var serverConfiguration = serverData.ToServerConfiguration();
|
||||
|
||||
var server = GetServer(serverId);
|
||||
|
||||
if (server == null)
|
||||
await InitializeServer(serverConfiguration, []);
|
||||
else
|
||||
server.UpdateConfiguration(serverConfiguration);
|
||||
}
|
||||
|
||||
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.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();
|
||||
}
|
||||
|
||||
public Server? GetServer(int id)
|
||||
@@ -197,7 +254,7 @@ public class ServerService : IHostedLifecycleService
|
||||
lock (Servers)
|
||||
return Servers.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Docker.DotNet;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using MoonCore.Configuration;
|
||||
using MoonCore.EnvConfiguration;
|
||||
using MoonCore.Extended.Extensions;
|
||||
@@ -41,6 +44,7 @@ public class Startup
|
||||
await RegisterAppConfiguration();
|
||||
await RegisterLogging();
|
||||
await RegisterBase();
|
||||
await RegisterAuth();
|
||||
await RegisterDocker();
|
||||
await RegisterServers();
|
||||
await RegisterSignalR();
|
||||
@@ -49,6 +53,7 @@ public class Startup
|
||||
await BuildWebApplication();
|
||||
|
||||
await UseBase();
|
||||
await UseAuth();
|
||||
await UseCors();
|
||||
await UseBaseMiddleware();
|
||||
|
||||
@@ -289,4 +294,40 @@ public class Startup
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Authentication
|
||||
|
||||
private Task RegisterAuth()
|
||||
{
|
||||
WebApplicationBuilder.Services
|
||||
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.TokenValidationParameters = new()
|
||||
{
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
|
||||
Configuration.Security.Token
|
||||
)),
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateAudience = false,
|
||||
ValidateIssuer = false,
|
||||
ClockSkew = TimeSpan.Zero
|
||||
};
|
||||
});
|
||||
|
||||
WebApplicationBuilder.Services.AddAuthorization();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task UseAuth()
|
||||
{
|
||||
WebApplication.UseAuthentication();
|
||||
WebApplication.UseAuthorization();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user