mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-29 16:11:05 +01:00
Various fixups
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models
|
||||
@@ -48,6 +49,13 @@ namespace Tgstation.Server.Api.Models
|
||||
[Permissions(WriteRight = InstanceManagerRights.SetAutoUpdate)]
|
||||
public int? AutoUpdateInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Job"/> representing a change of <see cref="Path"/>
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true)]
|
||||
[NotMapped]
|
||||
public Job MoveJob { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Instance CloneMetadata() => new Instance
|
||||
{
|
||||
|
||||
@@ -47,6 +47,10 @@ namespace Tgstation.Server.Api.Rights
|
||||
/// <summary>
|
||||
/// User can change <see cref="Models.Instance.AutoUpdateInterval"/>
|
||||
/// </summary>
|
||||
SetAutoUpdate = 256
|
||||
SetAutoUpdate = 256,
|
||||
/// <summary>
|
||||
/// User can cancel move operations
|
||||
/// </summary>
|
||||
CancelMove = 512,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -40,6 +41,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
readonly IApplication application;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="InstanceManager"/>
|
||||
/// </summary>
|
||||
readonly ILogger<InstanceManager> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Map of <see cref="Api.Models.Instance.Id"/>s to respective <see cref="IInstance"/>s
|
||||
/// </summary>
|
||||
@@ -56,12 +62,14 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="ioManager">The value of <paramref name="ioManager"/></param>
|
||||
/// <param name="databaseContextFactory">The value of <paramref name="databaseContextFactory"/></param>
|
||||
/// <param name="application">The value of <see cref="application"/></param>
|
||||
public InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application)
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILogger<InstanceManager> logger)
|
||||
{
|
||||
this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
|
||||
this.application = application ?? throw new ArgumentNullException(nameof(application));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
instances = new Dictionary<long, IInstance>();
|
||||
interopConsumers = new Dictionary<string, IInteropConsumer>();
|
||||
@@ -93,24 +101,11 @@ namespace Tgstation.Server.Host.Components
|
||||
if (newPath == null)
|
||||
throw new ArgumentNullException(nameof(newPath));
|
||||
if (instance.Online.Value)
|
||||
await OfflineInstance(instance, cancellationToken).ConfigureAwait(false);
|
||||
Task instanceOnlineTask = null;
|
||||
try
|
||||
{
|
||||
var oldPath = instance.Path;
|
||||
await ioManager.CopyDirectory(oldPath, newPath, null, cancellationToken).ConfigureAwait(false);
|
||||
instance.Path = ioManager.ResolvePath(newPath);
|
||||
instanceOnlineTask = OnlineInstance(instance, default);
|
||||
await ioManager.DeleteDirectory(oldPath, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (instance.Online.Value)
|
||||
if (instanceOnlineTask == null)
|
||||
await OnlineInstance(instance, default).ConfigureAwait(false);
|
||||
else
|
||||
await instanceOnlineTask.ConfigureAwait(false);
|
||||
}
|
||||
throw new InvalidOperationException("Cannot move an online instance!");
|
||||
var oldPath = instance.Path;
|
||||
await ioManager.CopyDirectory(oldPath, newPath, null, cancellationToken).ConfigureAwait(false);
|
||||
instance.Path = ioManager.ResolvePath(newPath);
|
||||
await ioManager.DeleteDirectory(oldPath, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -118,6 +113,7 @@ namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
if (metadata == null)
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
logger.LogInformation("Offlining instance ID {0}", metadata.Id);
|
||||
IInstance instance;
|
||||
lock (this)
|
||||
{
|
||||
@@ -140,6 +136,7 @@ namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
if (metadata == null)
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
logger.LogInformation("Onlining instance ID {0} ({1}) at {2}", metadata.Id, metadata.Name, metadata.Path);
|
||||
var instance = instanceFactory.CreateInstance(metadata, this);
|
||||
try
|
||||
{
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
var byondManager = instanceManager.GetInstance(Instance).ByondManager;
|
||||
|
||||
//remove cruff fields
|
||||
var installingVersion = new Version(model.Version.Major, model.Version.Major);
|
||||
var installingVersion = new Version(model.Version.Major, model.Version.Minor);
|
||||
|
||||
var result = new Api.Models.Byond();
|
||||
|
||||
|
||||
@@ -272,27 +272,58 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var oldAutoStart = originalModel.DreamDaemonSettings.AutoStart;
|
||||
try
|
||||
{
|
||||
if (originalOnline && model.Online.Value == false)
|
||||
await instanceManager.OfflineInstance(originalModel, cancellationToken).ConfigureAwait(false);
|
||||
else if (!originalOnline && model.Online.Value == true)
|
||||
{
|
||||
//force autostart false here because we don't want any long running jobs right now
|
||||
//remember to document this
|
||||
originalModel.DreamDaemonSettings.AutoStart = false;
|
||||
await instanceManager.OnlineInstance(originalModel, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError("Error changing instance online state! Exception: {0}", e);
|
||||
originalModel.Online = originalOnline;
|
||||
originalModel.DreamDaemonSettings.AutoStart = oldAutoStart;
|
||||
if (originalModelPath != null)
|
||||
originalModel.Path = originalModelPath;
|
||||
await DatabaseContext.Save(default).ConfigureAwait(false);
|
||||
throw;
|
||||
}
|
||||
|
||||
var api = originalModel.ToApi();
|
||||
if (originalModelPath != null)
|
||||
await ioManager.MoveDirectory(originalModelPath, model.Path, cancellationToken).ConfigureAwait(false);
|
||||
{
|
||||
var job = new Models.Job
|
||||
{
|
||||
Description = "Move instance location",
|
||||
Instance = Instance,
|
||||
CancelRightsType = RightsType.InstanceManager,
|
||||
CancelRight = (int)InstanceManagerRights.CancelMove,
|
||||
StartedBy = AuthenticationContext.User
|
||||
};
|
||||
|
||||
return Json(originalModel.ToApi());
|
||||
await jobManager.RegisterOperation(job, async (paramJob, serviceProvider, ct) => {
|
||||
try
|
||||
{
|
||||
await instanceManager.MoveInstance(Instance, originalModel.Path, ct).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
originalModel.Path = originalModelPath;
|
||||
await DatabaseContext.Save(default).ConfigureAwait(false);
|
||||
throw;
|
||||
}
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
api.MoveJob = job.ToApi();
|
||||
}
|
||||
|
||||
return Json(api);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -37,18 +37,12 @@ namespace Tgstation.Server.Host.Controllers
|
||||
[TgsAuthorize]
|
||||
public override async Task<IActionResult> List(CancellationToken cancellationToken)
|
||||
{
|
||||
IQueryable<Job> query = DatabaseContext.Jobs;
|
||||
if (Instance != null)
|
||||
//you KNOW this will need pagination eventually right?
|
||||
var jobs = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).Select(x => new Api.Models.Job
|
||||
{
|
||||
if (AuthenticationContext.InstanceUser?.AnyRights != true)
|
||||
return Forbid();
|
||||
query = query.Where(x => x.Instance.Id == Instance.Id);
|
||||
}
|
||||
else
|
||||
query = query.Where(x => x.Instance == null);
|
||||
|
||||
var jobs = await query.Where(x => x.StoppedAt == null).ToListAsync(cancellationToken).ConfigureAwait(false);
|
||||
return Json(jobs.Select(x => x.ToApi()));
|
||||
Id = x.Id
|
||||
}).ToListAsync(cancellationToken).ConfigureAwait(false);
|
||||
return Json(jobs);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -60,12 +54,12 @@ namespace Tgstation.Server.Host.Controllers
|
||||
if (job == default(Job))
|
||||
return NotFound();
|
||||
|
||||
if (job.StoppedAt != null)
|
||||
return StatusCode((int)HttpStatusCode.Gone);
|
||||
|
||||
if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
|
||||
return Forbid();
|
||||
|
||||
if(job.StoppedAt != null)
|
||||
return StatusCode((int)HttpStatusCode.Gone);
|
||||
|
||||
await jobManager.CancelJob(job, AuthenticationContext.User, cancellationToken).ConfigureAwait(false);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -172,6 +172,8 @@ namespace Tgstation.Server.Host.Core
|
||||
var databaseContext = scope.ServiceProvider.GetRequiredService<IDatabaseContext>();
|
||||
job = new Job { Id = job.Id };
|
||||
databaseContext.Jobs.Attach(job);
|
||||
user = new User { Id = user.Id };
|
||||
databaseContext.Users.Attach(user);
|
||||
job.CancelledBy = user;
|
||||
await databaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user