mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-27 07:04:57 +01:00
BYOND believable
This commit is contained in:
@@ -9,12 +9,6 @@ namespace Tgstation.Server.Api.Models
|
||||
[Model(RightsType.Byond, RequiresInstance = true)]
|
||||
public sealed class Byond
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ByondStatus"/> for the <see cref="Byond"/> installation
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true, ReadRight = ByondRights.ReadStatus)]
|
||||
public ByondStatus ByondStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.Version"/> of the <see cref="Byond"/> installation used for new compiles. Will be <see langword="null"/> if the user does not have permission to view it or there is no BYOND version installed. Only considers the <see cref="Version.Major"/> and <see cref="Version.Minor"/> numbers
|
||||
/// </summary>
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
namespace Tgstation.Server.Api.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The status of a <see cref="Byond"/> update job
|
||||
/// </summary>
|
||||
#pragma warning disable CA1717 // Only FlagsAttribute enums should have plural names
|
||||
public enum ByondStatus
|
||||
#pragma warning restore CA1717 // Only FlagsAttribute enums should have plural names
|
||||
{
|
||||
/// <summary>
|
||||
/// No update in progress
|
||||
/// </summary>
|
||||
Idle,
|
||||
/// <summary>
|
||||
/// Preparing to update
|
||||
/// </summary>
|
||||
Starting,
|
||||
/// <summary>
|
||||
/// Revision is downloading
|
||||
/// </summary>
|
||||
Downloading,
|
||||
/// <summary>
|
||||
/// Revision is deflating
|
||||
/// </summary>
|
||||
Staging,
|
||||
/// <summary>
|
||||
/// Revision is ready and waiting for DreamDaemon reboot
|
||||
/// </summary>
|
||||
Staged,
|
||||
/// <summary>
|
||||
/// Revision is being applied
|
||||
/// </summary>
|
||||
Updating,
|
||||
/// <summary>
|
||||
/// User does not have permission to view the <see cref="ByondStatus"/>
|
||||
/// </summary>
|
||||
Hidden,
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Host.IO;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class Byond : IByond
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for <see cref="Byond"/>
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for <see cref="Byond"/>
|
||||
/// </summary>
|
||||
readonly ILogger<Byond> logger;
|
||||
|
||||
/// <summary>
|
||||
/// List of installed BYOND <see cref="Version"/>s
|
||||
/// </summary>
|
||||
readonly List<Version> installedVersions;
|
||||
|
||||
/// <summary>
|
||||
/// Construct <see cref="Byond"/>
|
||||
/// </summary>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public Byond(IIOManager ioManager, ILogger<Byond> logger)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ChangeVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ClearCache(CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Version> GetVersion(CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IByondExecutableLock UseExecutables(Version requiredVersion)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Host.IO;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class ByondManager : IByondManager
|
||||
{
|
||||
const string VersionFileName = "Version.txt";
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByondInstaller"/> for the <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
readonly IByondInstaller byondInstaller;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
readonly ILogger<ByondManager> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Map of byond <see cref="Version"/>s to <see cref="Task"/>s that complete when they are installed
|
||||
/// </summary>
|
||||
readonly Dictionary<string, Task> installedVersions;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="byondInstaller">The value of <see cref="byondInstaller"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public ByondManager(IIOManager ioManager, IByondInstaller byondInstaller, ILogger<ByondManager> logger)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
static string VersionKey(Version version) => new Version(version.Major, version.Minor).ToString();
|
||||
|
||||
async Task InstallVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
var ourTcs = new TaskCompletionSource<object>();
|
||||
Task inProgressTask;
|
||||
|
||||
var versionKey = VersionKey(version);
|
||||
bool installed;
|
||||
lock (installedVersions)
|
||||
{
|
||||
installed = installedVersions.TryGetValue(versionKey, out inProgressTask);
|
||||
if (!installed)
|
||||
installedVersions.Add(versionKey, ourTcs.Task);
|
||||
}
|
||||
if(installed)
|
||||
using (cancellationToken.Register(() => ourTcs.SetCanceled()))
|
||||
{
|
||||
await Task.WhenAny(ourTcs.Task, inProgressTask).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var downloadTask = byondInstaller.DownloadVersion(version, cancellationToken);
|
||||
|
||||
//okay up to us to install it then
|
||||
await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
|
||||
await ioManager.CreateDirectory(versionKey, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var resolvedPath = ioManager.ResolvePath(versionKey);
|
||||
using (var zipBytes = await downloadTask.ConfigureAwait(false))
|
||||
using (var archive = new ZipArchive(zipBytes))
|
||||
await Task.Factory.StartNew(() => archive.ExtractToDirectory(resolvedPath), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
|
||||
await byondInstaller.InstallByond(resolvedPath, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
//make sure to do this last because this is what tells us we have a valid version
|
||||
await ioManager.WriteAllBytes(ioManager.ConcatPath(versionKey, VersionFileName), Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ChangeVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ClearCache(CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Version> GetVersion(CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IByondExecutableLock UseExecutables(Version requiredVersion)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,9 +39,9 @@ namespace Tgstation.Server.Host.Components
|
||||
public CompilerStatus Status { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByond"/> for <see cref="DreamMaker"/>
|
||||
/// The <see cref="IByondManager"/> for <see cref="DreamMaker"/>
|
||||
/// </summary>
|
||||
readonly IByond byond;
|
||||
readonly IByondManager byond;
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for <see cref="DreamMaker"/>
|
||||
/// </summary>
|
||||
@@ -82,7 +82,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="application">The value of <see cref="application"/></param>
|
||||
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public DreamMaker(IByond byond, IIOManager ioManager, IConfiguration configuration, ISessionControllerFactory sessionControllerFactory, ICompileJobConsumer compileJobConsumer, IApplication application, IEventConsumer eventConsumer, ILogger<DreamMaker> logger)
|
||||
public DreamMaker(IByondManager byond, IIOManager ioManager, IConfiguration configuration, ISessionControllerFactory sessionControllerFactory, ICompileJobConsumer compileJobConsumer, IApplication application, IEventConsumer eventConsumer, ILogger<DreamMaker> logger)
|
||||
{
|
||||
this.byond = byond;
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Stream = System.IO.Stream;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// For downloading and installing BYOND extractions
|
||||
/// </summary>
|
||||
interface IByondInstaller
|
||||
{
|
||||
/// <summary>
|
||||
/// Download a given BYOND <paramref name="version"/>
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="Version"/> of BYOND to download</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="Stream"/> of the zipfile</returns>
|
||||
Task<Stream> DownloadVersion(Version version, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Does actions necessary to get an extracted BYOND installation working
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the BYOND installation</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns></returns>
|
||||
Task InstallByond(string path, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -7,17 +7,17 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <summary>
|
||||
/// For managing the BYOND installation
|
||||
/// </summary>
|
||||
public interface IByond
|
||||
public interface IByondManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Change the current BYOND version
|
||||
/// Change the active BYOND version
|
||||
/// </summary>
|
||||
/// <param name="version">The new <see cref="Version"/></param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
Task ChangeVersion(Version version, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Get the currently installed BYOND version
|
||||
/// Get the currently active BYOND version
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>The current BYOND version</returns>
|
||||
@@ -16,9 +16,9 @@ namespace Tgstation.Server.Host.Components
|
||||
IRepositoryManager RepositoryManager { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByond"/> for the <see cref="IInstance"/>
|
||||
/// The <see cref="IByondManager"/> for the <see cref="IInstance"/>
|
||||
/// </summary>
|
||||
IByond Byond { get; }
|
||||
IByondManager ByondManager { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IDreamMaker"/> for the <see cref="IInstance"/>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Tgstation.Server.Host.Components
|
||||
public IRepositoryManager RepositoryManager { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IByond Byond { get; }
|
||||
public IByondManager ByondManager { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDreamMaker DreamMaker { get; }
|
||||
@@ -59,11 +59,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
CancellationTokenSource timerCts;
|
||||
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByond byond, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory)
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory)
|
||||
{
|
||||
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
|
||||
RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
|
||||
Byond = byond ?? throw new ArgumentNullException(nameof(byond));
|
||||
ByondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
|
||||
DreamMaker = dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker));
|
||||
watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
|
||||
Chat = chat ?? throw new ArgumentNullException(nameof(chat));
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Tgstation.Server.Host.Components
|
||||
|
||||
var repoManager = new RepositoryManager(metadata.RepositorySettings, repoIoManager);
|
||||
|
||||
IByond byond = null;
|
||||
IByondManager byond = null;
|
||||
var configuration = new Configuration(configurationIoManager, synchronousIOManager, symlinkFactory, loggerFactory.CreateLogger<Configuration>());
|
||||
|
||||
var chat = chatFactory.CreateChat();
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
readonly IExecutor executor;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByond"/> for the <see cref="SessionControllerFactory"/>
|
||||
/// The <see cref="IByondManager"/> for the <see cref="SessionControllerFactory"/>
|
||||
/// </summary>
|
||||
readonly IByond byond;
|
||||
readonly IByondManager byond;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByondTopicSender"/> for the <see cref="SessionControllerFactory"/>
|
||||
@@ -81,7 +81,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="chat">The value of <see cref="chat"/></param>
|
||||
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/></param>
|
||||
public SessionControllerFactory(IExecutor executor, IByond byond, IByondTopicSender byondTopicSender, IInteropRegistrar interopRegistrar, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, ILoggerFactory loggerFactory, Models.Instance instance)
|
||||
public SessionControllerFactory(IExecutor executor, IByondManager byond, IByondTopicSender byondTopicSender, IInteropRegistrar interopRegistrar, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, ILoggerFactory loggerFactory, Models.Instance instance)
|
||||
{
|
||||
this.executor = executor ?? throw new ArgumentNullException(nameof(executor));
|
||||
this.byond = byond ?? throw new ArgumentNullException(nameof(byond));
|
||||
|
||||
Reference in New Issue
Block a user