aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJPVenson <github@jpb.email>2025-04-21 05:06:50 +0300
committerGitHub <noreply@github.com>2025-04-20 20:06:50 -0600
commita0931baa8eb879898f4bc4049176ed3bdb4d80d1 (patch)
tree69bca19c69930fb83a166ae9944273c4dd66fdb9
parent5e4bd744c07d44d75c8e9eb7b6dc03b7ff4f147c (diff)
Add Api and startup check for sufficient storage capacity (#13888)
-rw-r--r--Emby.Server.Implementations/SystemManager.cs34
-rw-r--r--Jellyfin.Api/Controllers/SystemController.cs14
-rw-r--r--Jellyfin.Api/Models/SystemInfoDtos/FolderStorageDto.cs46
-rw-r--r--Jellyfin.Api/Models/SystemInfoDtos/LibraryStorageDto.cs37
-rw-r--r--Jellyfin.Api/Models/SystemInfoDtos/SystemStorageDto.cs67
-rw-r--r--Jellyfin.Server.Implementations/StorageHelpers/StorageHelper.cs109
-rw-r--r--Jellyfin.Server/Program.cs4
-rw-r--r--MediaBrowser.Controller/ISystemManager.cs7
-rw-r--r--MediaBrowser.Model/System/FolderStorageInfo.cs32
-rw-r--r--MediaBrowser.Model/System/LibraryStorageInfo.cs25
-rw-r--r--MediaBrowser.Model/System/SystemInfo.cs254
-rw-r--r--MediaBrowser.Model/System/SystemStorageInfo.cs56
12 files changed, 560 insertions, 125 deletions
diff --git a/Emby.Server.Implementations/SystemManager.cs b/Emby.Server.Implementations/SystemManager.cs
index 5936df7f1..92b59b23c 100644
--- a/Emby.Server.Implementations/SystemManager.cs
+++ b/Emby.Server.Implementations/SystemManager.cs
@@ -1,9 +1,12 @@
+using System;
using System.Linq;
using System.Threading.Tasks;
+using Jellyfin.Server.Implementations.StorageHelpers;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Model.System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
@@ -19,6 +22,7 @@ public class SystemManager : ISystemManager
private readonly IServerConfigurationManager _configurationManager;
private readonly IStartupOptions _startupOptions;
private readonly IInstallationManager _installationManager;
+ private readonly ILibraryManager _libraryManager;
/// <summary>
/// Initializes a new instance of the <see cref="SystemManager"/> class.
@@ -29,13 +33,15 @@ public class SystemManager : ISystemManager
/// <param name="configurationManager">Instance of <see cref="IServerConfigurationManager"/>.</param>
/// <param name="startupOptions">Instance of <see cref="IStartupOptions"/>.</param>
/// <param name="installationManager">Instance of <see cref="IInstallationManager"/>.</param>
+ /// <param name="libraryManager">Instance of <see cref="ILibraryManager"/>.</param>
public SystemManager(
IHostApplicationLifetime applicationLifetime,
IServerApplicationHost applicationHost,
IServerApplicationPaths applicationPaths,
IServerConfigurationManager configurationManager,
IStartupOptions startupOptions,
- IInstallationManager installationManager)
+ IInstallationManager installationManager,
+ ILibraryManager libraryManager)
{
_applicationLifetime = applicationLifetime;
_applicationHost = applicationHost;
@@ -43,6 +49,7 @@ public class SystemManager : ISystemManager
_configurationManager = configurationManager;
_startupOptions = startupOptions;
_installationManager = installationManager;
+ _libraryManager = libraryManager;
}
/// <inheritdoc />
@@ -57,6 +64,7 @@ public class SystemManager : ISystemManager
WebSocketPortNumber = _applicationHost.HttpPort,
CompletedInstallations = _installationManager.CompletedInstallations.ToArray(),
Id = _applicationHost.SystemId,
+#pragma warning disable CS0618 // Type or member is obsolete
ProgramDataPath = _applicationPaths.ProgramDataPath,
WebPath = _applicationPaths.WebPath,
LogPath = _applicationPaths.LogDirectoryPath,
@@ -64,6 +72,7 @@ public class SystemManager : ISystemManager
InternalMetadataPath = _applicationPaths.InternalMetadataPath,
CachePath = _applicationPaths.CachePath,
TranscodingTempPath = _configurationManager.GetTranscodePath(),
+#pragma warning restore CS0618 // Type or member is obsolete
ServerName = _applicationHost.FriendlyName,
LocalAddress = _applicationHost.GetSmartApiUrl(request),
StartupWizardCompleted = _configurationManager.CommonConfiguration.IsStartupWizardCompleted,
@@ -73,6 +82,29 @@ public class SystemManager : ISystemManager
};
}
+ /// <inheritdoc/>
+ public SystemStorageInfo GetSystemStorageInfo()
+ {
+ var virtualFolderInfos = _libraryManager.GetVirtualFolders().Select(e => new LibraryStorageInfo()
+ {
+ Id = Guid.Parse(e.ItemId),
+ Name = e.Name,
+ Folders = e.Locations.Select(f => StorageHelper.GetFreeSpaceOf(f)).ToArray()
+ });
+
+ return new SystemStorageInfo()
+ {
+ ProgramDataFolder = StorageHelper.GetFreeSpaceOf(_applicationPaths.ProgramDataPath),
+ WebFolder = StorageHelper.GetFreeSpaceOf(_applicationPaths.WebPath),
+ LogFolder = StorageHelper.GetFreeSpaceOf(_applicationPaths.LogDirectoryPath),
+ ImageCacheFolder = StorageHelper.GetFreeSpaceOf(_applicationPaths.ImageCachePath),
+ InternalMetadataFolder = StorageHelper.GetFreeSpaceOf(_applicationPaths.InternalMetadataPath),
+ CacheFolder = StorageHelper.GetFreeSpaceOf(_applicationPaths.CachePath),
+ TranscodingTempFolder = StorageHelper.GetFreeSpaceOf(_configurationManager.GetTranscodePath()),
+ Libraries = virtualFolderInfos.ToArray()
+ };
+ }
+
/// <inheritdoc />
public PublicSystemInfo GetPublicSystemInfo(HttpRequest request)
{
diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs
index 0ee11c070..07a1f7650 100644
--- a/Jellyfin.Api/Controllers/SystemController.cs
+++ b/Jellyfin.Api/Controllers/SystemController.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Net.Mime;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
+using Jellyfin.Api.Models.SystemInfoDtos;
using MediaBrowser.Common.Api;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
@@ -72,6 +73,19 @@ public class SystemController : BaseJellyfinApiController
=> _systemManager.GetSystemInfo(Request);
/// <summary>
+ /// Gets information about the server.
+ /// </summary>
+ /// <response code="200">Information retrieved.</response>
+ /// <response code="403">User does not have permission to retrieve information.</response>
+ /// <returns>A <see cref="SystemInfo"/> with info about the system.</returns>
+ [HttpGet("Info/Storage")]
+ [Authorize(Policy = Policies.RequiresElevation)]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ public ActionResult<SystemStorageDto> GetSystemStorage()
+ => Ok(SystemStorageDto.FromSystemStorageInfo(_systemManager.GetSystemStorageInfo()));
+
+ /// <summary>
/// Gets public information about the server.
/// </summary>
/// <response code="200">Information retrieved.</response>
diff --git a/Jellyfin.Api/Models/SystemInfoDtos/FolderStorageDto.cs b/Jellyfin.Api/Models/SystemInfoDtos/FolderStorageDto.cs
new file mode 100644
index 000000000..00a965898
--- /dev/null
+++ b/Jellyfin.Api/Models/SystemInfoDtos/FolderStorageDto.cs
@@ -0,0 +1,46 @@
+using MediaBrowser.Model.System;
+
+namespace Jellyfin.Api.Models.SystemInfoDtos;
+
+/// <summary>
+/// Contains information about a specific folder.
+/// </summary>
+public record FolderStorageDto
+{
+ /// <summary>
+ /// Gets the path of the folder in question.
+ /// </summary>
+ public required string Path { get; init; }
+
+ /// <summary>
+ /// Gets the free space of the underlying storage device of the <see cref="Path"/>.
+ /// </summary>
+ public long FreeSpace { get; init; }
+
+ /// <summary>
+ /// Gets the used space of the underlying storage device of the <see cref="Path"/>.
+ /// </summary>
+ public long UsedSpace { get; init; }
+
+ /// <summary>
+ /// Gets the kind of storage device of the <see cref="Path"/>.
+ /// </summary>
+ public string? StorageType { get; init; }
+
+ /// <summary>
+ /// Gets the Device Identifier.
+ /// </summary>
+ public string? DeviceId { get; init; }
+
+ internal static FolderStorageDto FromFolderStorageInfo(FolderStorageInfo model)
+ {
+ return new()
+ {
+ Path = model.Path,
+ FreeSpace = model.FreeSpace,
+ UsedSpace = model.UsedSpace,
+ StorageType = model.StorageType,
+ DeviceId = model.DeviceId
+ };
+ }
+}
diff --git a/Jellyfin.Api/Models/SystemInfoDtos/LibraryStorageDto.cs b/Jellyfin.Api/Models/SystemInfoDtos/LibraryStorageDto.cs
new file mode 100644
index 000000000..c138324d2
--- /dev/null
+++ b/Jellyfin.Api/Models/SystemInfoDtos/LibraryStorageDto.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MediaBrowser.Model.System;
+
+namespace Jellyfin.Api.Models.SystemInfoDtos;
+
+/// <summary>
+/// Contains informations about a libraries storage informations.
+/// </summary>
+public record LibraryStorageDto
+{
+ /// <summary>
+ /// Gets or sets the Library Id.
+ /// </summary>
+ public required Guid Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the library.
+ /// </summary>
+ public required string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the storage informations about the folders used in a library.
+ /// </summary>
+ public required IReadOnlyCollection<FolderStorageDto> Folders { get; set; }
+
+ internal static LibraryStorageDto FromLibraryStorageModel(LibraryStorageInfo model)
+ {
+ return new()
+ {
+ Id = model.Id,
+ Name = model.Name,
+ Folders = model.Folders.Select(FolderStorageDto.FromFolderStorageInfo).ToArray()
+ };
+ }
+}
diff --git a/Jellyfin.Api/Models/SystemInfoDtos/SystemStorageDto.cs b/Jellyfin.Api/Models/SystemInfoDtos/SystemStorageDto.cs
new file mode 100644
index 000000000..a09042439
--- /dev/null
+++ b/Jellyfin.Api/Models/SystemInfoDtos/SystemStorageDto.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MediaBrowser.Model.System;
+
+namespace Jellyfin.Api.Models.SystemInfoDtos;
+
+/// <summary>
+/// Contains informations about the systems storage.
+/// </summary>
+public record SystemStorageDto
+{
+ /// <summary>
+ /// Gets or sets the Storage information of the program data folder.
+ /// </summary>
+ public required FolderStorageDto ProgramDataFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Storage information of the web UI resources folder.
+ /// </summary>
+ public required FolderStorageDto WebFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Storage information of the folder where images are cached.
+ /// </summary>
+ public required FolderStorageDto ImageCacheFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Storage information of the cache folder.
+ /// </summary>
+ public required FolderStorageDto CacheFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Storage information of the folder where logfiles are saved to.
+ /// </summary>
+ public required FolderStorageDto LogFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Storage information of the folder where metadata is stored.
+ /// </summary>
+ public required FolderStorageDto InternalMetadataFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Storage information of the transcoding cache.
+ /// </summary>
+ public required FolderStorageDto TranscodingTempFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the storage informations of all libraries.
+ /// </summary>
+ public required IReadOnlyCollection<LibraryStorageDto> Libraries { get; set; }
+
+ internal static SystemStorageDto FromSystemStorageInfo(SystemStorageInfo model)
+ {
+ return new SystemStorageDto()
+ {
+ ProgramDataFolder = FolderStorageDto.FromFolderStorageInfo(model.ProgramDataFolder),
+ WebFolder = FolderStorageDto.FromFolderStorageInfo(model.WebFolder),
+ ImageCacheFolder = FolderStorageDto.FromFolderStorageInfo(model.ImageCacheFolder),
+ CacheFolder = FolderStorageDto.FromFolderStorageInfo(model.CacheFolder),
+ LogFolder = FolderStorageDto.FromFolderStorageInfo(model.LogFolder),
+ InternalMetadataFolder = FolderStorageDto.FromFolderStorageInfo(model.InternalMetadataFolder),
+ TranscodingTempFolder = FolderStorageDto.FromFolderStorageInfo(model.TranscodingTempFolder),
+ Libraries = model.Libraries.Select(LibraryStorageDto.FromLibraryStorageModel).ToArray()
+ };
+ }
+}
diff --git a/Jellyfin.Server.Implementations/StorageHelpers/StorageHelper.cs b/Jellyfin.Server.Implementations/StorageHelpers/StorageHelper.cs
new file mode 100644
index 000000000..635644179
--- /dev/null
+++ b/Jellyfin.Server.Implementations/StorageHelpers/StorageHelper.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Globalization;
+using System.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.System;
+using Microsoft.Extensions.Logging;
+
+namespace Jellyfin.Server.Implementations.StorageHelpers;
+
+/// <summary>
+/// Contains methods to help with checking for storage and returning storage data for jellyfin folders.
+/// </summary>
+public static class StorageHelper
+{
+ private const long TwoGigabyte = 2_147_483_647L;
+ private const long FiveHundredAndTwelveMegaByte = 536_870_911L;
+ private static readonly string[] _byteHumanizedSuffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB"];
+
+ /// <summary>
+ /// Tests the available storage capacity on the jellyfin paths with estimated minimum values.
+ /// </summary>
+ /// <param name="applicationPaths">The application paths.</param>
+ /// <param name="logger">Logger.</param>
+ public static void TestCommonPathsForStorageCapacity(IApplicationPaths applicationPaths, ILogger logger)
+ {
+ TestDataDirectorySize(applicationPaths.DataPath, logger, TwoGigabyte);
+ TestDataDirectorySize(applicationPaths.LogDirectoryPath, logger, FiveHundredAndTwelveMegaByte);
+ TestDataDirectorySize(applicationPaths.CachePath, logger, TwoGigabyte);
+ TestDataDirectorySize(applicationPaths.ProgramDataPath, logger, TwoGigabyte);
+ TestDataDirectorySize(applicationPaths.TempDirectory, logger, TwoGigabyte);
+ }
+
+ /// <summary>
+ /// Gets the free space of a specific directory.
+ /// </summary>
+ /// <param name="path">Path to a folder.</param>
+ /// <returns>The number of bytes available space.</returns>
+ public static FolderStorageInfo GetFreeSpaceOf(string path)
+ {
+ try
+ {
+ var driveInfo = new DriveInfo(path);
+ return new FolderStorageInfo()
+ {
+ Path = path,
+ FreeSpace = driveInfo.AvailableFreeSpace,
+ UsedSpace = driveInfo.TotalSize - driveInfo.AvailableFreeSpace,
+ StorageType = driveInfo.DriveType.ToString(),
+ DeviceId = driveInfo.Name,
+ };
+ }
+ catch
+ {
+ return new FolderStorageInfo()
+ {
+ Path = path,
+ FreeSpace = -1,
+ UsedSpace = -1,
+ StorageType = null,
+ DeviceId = null
+ };
+ }
+ }
+
+ /// <summary>
+ /// Gets the underlying drive data from a given path and checks if the available storage capacity matches the threshold.
+ /// </summary>
+ /// <param name="path">The path to a folder to evaluate.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="threshold">The threshold to check for or -1 to just log the data.</param>
+ /// <exception cref="InvalidOperationException">Thrown when the threshold is not available on the underlying storage.</exception>
+ private static void TestDataDirectorySize(string path, ILogger logger, long threshold = -1)
+ {
+ logger.LogDebug("Check path {TestPath} for storage capacity", path);
+ var drive = new DriveInfo(path);
+ if (threshold != -1 && drive.AvailableFreeSpace < threshold)
+ {
+ throw new InvalidOperationException($"The path `{path}` has insufficient free space. Required: at least {HumanizeStorageSize(threshold)}.");
+ }
+
+ logger.LogInformation(
+ "Storage path `{TestPath}` ({StorageType}) successfully checked with {FreeSpace} free which is over the minimum of {MinFree}.",
+ path,
+ drive.DriveType,
+ HumanizeStorageSize(drive.AvailableFreeSpace),
+ HumanizeStorageSize(threshold));
+ }
+
+ /// <summary>
+ /// Formats a size in bytes into a common human readable form.
+ /// </summary>
+ /// <remarks>
+ /// Taken and slightly modified from https://stackoverflow.com/a/4975942/1786007 .
+ /// </remarks>
+ /// <param name="byteCount">The size in bytes.</param>
+ /// <returns>A human readable approximate representation of the argument.</returns>
+ public static string HumanizeStorageSize(long byteCount)
+ {
+ if (byteCount == 0)
+ {
+ return $"0{_byteHumanizedSuffixes[0]}";
+ }
+
+ var bytes = Math.Abs(byteCount);
+ var place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
+ var num = Math.Round(bytes / Math.Pow(1024, place), 1);
+ return (Math.Sign(byteCount) * num).ToString(CultureInfo.InvariantCulture) + _byteHumanizedSuffixes[place];
+ }
+}
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index 55a4a0087..8d0bf73f6 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -11,6 +12,7 @@ using Emby.Server.Implementations;
using Jellyfin.Database.Implementations;
using Jellyfin.Server.Extensions;
using Jellyfin.Server.Helpers;
+using Jellyfin.Server.Implementations.StorageHelpers;
using Jellyfin.Server.ServerSetupApp;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
@@ -120,6 +122,8 @@ namespace Jellyfin.Server
}
}
+ StorageHelper.TestCommonPathsForStorageCapacity(appPaths, _loggerFactory.CreateLogger<Startup>());
+
StartupHelpers.PerformStaticInitialization();
await Migrations.MigrationRunner.RunPreStartup(appPaths, _loggerFactory).ConfigureAwait(false);
diff --git a/MediaBrowser.Controller/ISystemManager.cs b/MediaBrowser.Controller/ISystemManager.cs
index ef3034d2f..08344a1e5 100644
--- a/MediaBrowser.Controller/ISystemManager.cs
+++ b/MediaBrowser.Controller/ISystemManager.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.System;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
namespace MediaBrowser.Controller;
@@ -31,4 +32,10 @@ public interface ISystemManager
/// Starts the application shutdown process.
/// </summary>
void Shutdown();
+
+ /// <summary>
+ /// Gets the systems storage resources.
+ /// </summary>
+ /// <returns>The <see cref="SystemStorageInfo"/>.</returns>
+ SystemStorageInfo GetSystemStorageInfo();
}
diff --git a/MediaBrowser.Model/System/FolderStorageInfo.cs b/MediaBrowser.Model/System/FolderStorageInfo.cs
new file mode 100644
index 000000000..7b10e4ea5
--- /dev/null
+++ b/MediaBrowser.Model/System/FolderStorageInfo.cs
@@ -0,0 +1,32 @@
+namespace MediaBrowser.Model.System;
+
+/// <summary>
+/// Contains information about a specific folder.
+/// </summary>
+public record FolderStorageInfo
+{
+ /// <summary>
+ /// Gets the path of the folder in question.
+ /// </summary>
+ public required string Path { get; init; }
+
+ /// <summary>
+ /// Gets the free space of the underlying storage device of the <see cref="Path"/>.
+ /// </summary>
+ public long FreeSpace { get; init; }
+
+ /// <summary>
+ /// Gets the used space of the underlying storage device of the <see cref="Path"/>.
+ /// </summary>
+ public long UsedSpace { get; init; }
+
+ /// <summary>
+ /// Gets the kind of storage device of the <see cref="Path"/>.
+ /// </summary>
+ public string? StorageType { get; init; }
+
+ /// <summary>
+ /// Gets the Device Identifier.
+ /// </summary>
+ public string? DeviceId { get; init; }
+}
diff --git a/MediaBrowser.Model/System/LibraryStorageInfo.cs b/MediaBrowser.Model/System/LibraryStorageInfo.cs
new file mode 100644
index 000000000..d4111b29c
--- /dev/null
+++ b/MediaBrowser.Model/System/LibraryStorageInfo.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.System;
+
+/// <summary>
+/// Contains informations about a libraries storage informations.
+/// </summary>
+public class LibraryStorageInfo
+{
+ /// <summary>
+ /// Gets or sets the Library Id.
+ /// </summary>
+ public required Guid Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the library.
+ /// </summary>
+ public required string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the storage informations about the folders used in a library.
+ /// </summary>
+ public required IReadOnlyCollection<FolderStorageInfo> Folders { get; set; }
+}
diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs
index f37ac6a14..232a2a6bc 100644
--- a/MediaBrowser.Model/System/SystemInfo.cs
+++ b/MediaBrowser.Model/System/SystemInfo.cs
@@ -6,133 +6,139 @@ using System.Collections.Generic;
using System.ComponentModel;
using MediaBrowser.Model.Updates;
-namespace MediaBrowser.Model.System
+namespace MediaBrowser.Model.System;
+
+/// <summary>
+/// Class SystemInfo.
+/// </summary>
+public class SystemInfo : PublicSystemInfo
{
/// <summary>
- /// Class SystemInfo.
+ /// Initializes a new instance of the <see cref="SystemInfo" /> class.
/// </summary>
- public class SystemInfo : PublicSystemInfo
+ public SystemInfo()
{
- /// <summary>
- /// Initializes a new instance of the <see cref="SystemInfo" /> class.
- /// </summary>
- public SystemInfo()
- {
- CompletedInstallations = Array.Empty<InstallationInfo>();
- }
-
- /// <summary>
- /// Gets or sets the display name of the operating system.
- /// </summary>
- /// <value>The display name of the operating system.</value>
- [Obsolete("This is no longer set")]
- public string OperatingSystemDisplayName { get; set; } = string.Empty;
-
- /// <summary>
- /// Gets or sets the package name.
- /// </summary>
- /// <value>The value of the '-package' command line argument.</value>
- public string PackageName { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance has pending restart.
- /// </summary>
- /// <value><c>true</c> if this instance has pending restart; otherwise, <c>false</c>.</value>
- public bool HasPendingRestart { get; set; }
-
- public bool IsShuttingDown { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [supports library monitor].
- /// </summary>
- /// <value><c>true</c> if [supports library monitor]; otherwise, <c>false</c>.</value>
- public bool SupportsLibraryMonitor { get; set; }
-
- /// <summary>
- /// Gets or sets the web socket port number.
- /// </summary>
- /// <value>The web socket port number.</value>
- public int WebSocketPortNumber { get; set; }
-
- /// <summary>
- /// Gets or sets the completed installations.
- /// </summary>
- /// <value>The completed installations.</value>
- public InstallationInfo[] CompletedInstallations { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance can self restart.
- /// </summary>
- /// <value><c>true</c>.</value>
- [Obsolete("This is always true")]
- [DefaultValue(true)]
- public bool CanSelfRestart { get; set; } = true;
-
- [Obsolete("This is always false")]
- [DefaultValue(false)]
- public bool CanLaunchWebBrowser { get; set; } = false;
-
- /// <summary>
- /// Gets or sets the program data path.
- /// </summary>
- /// <value>The program data path.</value>
- public string ProgramDataPath { get; set; }
-
- /// <summary>
- /// Gets or sets the web UI resources path.
- /// </summary>
- /// <value>The web UI resources path.</value>
- public string WebPath { get; set; }
-
- /// <summary>
- /// Gets or sets the items by name path.
- /// </summary>
- /// <value>The items by name path.</value>
- public string ItemsByNamePath { get; set; }
-
- /// <summary>
- /// Gets or sets the cache path.
- /// </summary>
- /// <value>The cache path.</value>
- public string CachePath { get; set; }
-
- /// <summary>
- /// Gets or sets the log path.
- /// </summary>
- /// <value>The log path.</value>
- public string LogPath { get; set; }
-
- /// <summary>
- /// Gets or sets the internal metadata path.
- /// </summary>
- /// <value>The internal metadata path.</value>
- public string InternalMetadataPath { get; set; }
-
- /// <summary>
- /// Gets or sets the transcode path.
- /// </summary>
- /// <value>The transcode path.</value>
- public string TranscodingTempPath { get; set; }
-
- /// <summary>
- /// Gets or sets the list of cast receiver applications.
- /// </summary>
- public IReadOnlyList<CastReceiverApplication> CastReceiverApplications { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance has update available.
- /// </summary>
- /// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value>
- [Obsolete("This should be handled by the package manager")]
- [DefaultValue(false)]
- public bool HasUpdateAvailable { get; set; }
-
- [Obsolete("This isn't set correctly anymore")]
- [DefaultValue("System")]
- public string EncoderLocation { get; set; } = "System";
-
- [Obsolete("This is no longer set")]
- [DefaultValue("X64")]
- public string SystemArchitecture { get; set; } = "X64";
+ CompletedInstallations = Array.Empty<InstallationInfo>();
}
+
+ /// <summary>
+ /// Gets or sets the display name of the operating system.
+ /// </summary>
+ /// <value>The display name of the operating system.</value>
+ [Obsolete("This is no longer set")]
+ public string OperatingSystemDisplayName { get; set; } = string.Empty;
+
+ /// <summary>
+ /// Gets or sets the package name.
+ /// </summary>
+ /// <value>The value of the '-package' command line argument.</value>
+ public string PackageName { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance has pending restart.
+ /// </summary>
+ /// <value><c>true</c> if this instance has pending restart; otherwise, <c>false</c>.</value>
+ public bool HasPendingRestart { get; set; }
+
+ public bool IsShuttingDown { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether [supports library monitor].
+ /// </summary>
+ /// <value><c>true</c> if [supports library monitor]; otherwise, <c>false</c>.</value>
+ public bool SupportsLibraryMonitor { get; set; }
+
+ /// <summary>
+ /// Gets or sets the web socket port number.
+ /// </summary>
+ /// <value>The web socket port number.</value>
+ public int WebSocketPortNumber { get; set; }
+
+ /// <summary>
+ /// Gets or sets the completed installations.
+ /// </summary>
+ /// <value>The completed installations.</value>
+ public InstallationInfo[] CompletedInstallations { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance can self restart.
+ /// </summary>
+ /// <value><c>true</c>.</value>
+ [Obsolete("This is always true")]
+ [DefaultValue(true)]
+ public bool CanSelfRestart { get; set; } = true;
+
+ [Obsolete("This is always false")]
+ [DefaultValue(false)]
+ public bool CanLaunchWebBrowser { get; set; } = false;
+
+ /// <summary>
+ /// Gets or sets the program data path.
+ /// </summary>
+ /// <value>The program data path.</value>
+ [Obsolete("Use the newer SystemStorageDto instead")]
+ public string ProgramDataPath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the web UI resources path.
+ /// </summary>
+ /// <value>The web UI resources path.</value>
+ [Obsolete("Use the newer SystemStorageDto instead")]
+ public string WebPath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the items by name path.
+ /// </summary>
+ /// <value>The items by name path.</value>
+ [Obsolete("Use the newer SystemStorageDto instead")]
+ public string ItemsByNamePath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the cache path.
+ /// </summary>
+ /// <value>The cache path.</value>
+ [Obsolete("Use the newer SystemStorageDto instead")]
+ public string CachePath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the log path.
+ /// </summary>
+ /// <value>The log path.</value>
+ [Obsolete("Use the newer SystemStorageDto instead")]
+ public string LogPath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the internal metadata path.
+ /// </summary>
+ /// <value>The internal metadata path.</value>
+ [Obsolete("Use the newer SystemStorageDto instead")]
+ public string InternalMetadataPath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the transcode path.
+ /// </summary>
+ /// <value>The transcode path.</value>
+ [Obsolete("Use the newer SystemStorageDto instead")]
+ public string TranscodingTempPath { get; set; }
+
+ /// <summary>
+ /// Gets or sets the list of cast receiver applications.
+ /// </summary>
+ public IReadOnlyList<CastReceiverApplication> CastReceiverApplications { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance has update available.
+ /// </summary>
+ /// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value>
+ [Obsolete("This should be handled by the package manager")]
+ [DefaultValue(false)]
+ public bool HasUpdateAvailable { get; set; }
+
+ [Obsolete("This isn't set correctly anymore")]
+ [DefaultValue("System")]
+ public string EncoderLocation { get; set; } = "System";
+
+ [Obsolete("This is no longer set")]
+ [DefaultValue("X64")]
+ public string SystemArchitecture { get; set; } = "X64";
}
diff --git a/MediaBrowser.Model/System/SystemStorageInfo.cs b/MediaBrowser.Model/System/SystemStorageInfo.cs
new file mode 100644
index 000000000..42e7a37e0
--- /dev/null
+++ b/MediaBrowser.Model/System/SystemStorageInfo.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.System;
+
+/// <summary>
+/// Contains informations about the systems storage.
+/// </summary>
+public class SystemStorageInfo
+{
+ /// <summary>
+ /// Gets or sets the program data path.
+ /// </summary>
+ /// <value>The program data path.</value>
+ public required FolderStorageInfo ProgramDataFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the web UI resources path.
+ /// </summary>
+ /// <value>The web UI resources path.</value>
+ public required FolderStorageInfo WebFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the items by name path.
+ /// </summary>
+ /// <value>The items by name path.</value>
+ public required FolderStorageInfo ImageCacheFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the cache path.
+ /// </summary>
+ /// <value>The cache path.</value>
+ public required FolderStorageInfo CacheFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the log path.
+ /// </summary>
+ /// <value>The log path.</value>
+ public required FolderStorageInfo LogFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the internal metadata path.
+ /// </summary>
+ /// <value>The internal metadata path.</value>
+ public required FolderStorageInfo InternalMetadataFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the transcode path.
+ /// </summary>
+ /// <value>The transcode path.</value>
+ public required FolderStorageInfo TranscodingTempFolder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the storage informations of all libraries.
+ /// </summary>
+ public required IReadOnlyCollection<LibraryStorageInfo> Libraries { get; set; }
+}