New: Various HealthCheck Improvements
This commit is contained in:
parent
0321368cc3
commit
0f6f681438
|
@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
}
|
||||
}
|
||||
|
||||
public static void ShouldBeError(this Core.HealthCheck.HealthCheck result, string message = null)
|
||||
public static void ShouldBeError(this Core.HealthCheck.HealthCheck result, string message = null, string wikiFragment = null)
|
||||
{
|
||||
result.Type.Should().Be(HealthCheckResult.Error);
|
||||
|
||||
|
@ -44,6 +44,11 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
{
|
||||
result.Message.Should().Contain(message);
|
||||
}
|
||||
|
||||
if (wikiFragment.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
result.WikiUrl.Fragment.Should().Be(wikiFragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Localization;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class RemotePathMappingCheckFixture : CoreTest<RemotePathMappingCheck>
|
||||
{
|
||||
private string _downloadRootPath = @"c:\Test".AsOsAgnostic();
|
||||
private string _downloadItemPath = @"c:\Test\item".AsOsAgnostic();
|
||||
|
||||
private DownloadClientInfo _clientStatus;
|
||||
private DownloadClientItem _downloadItem;
|
||||
private Mock<IDownloadClient> _downloadClient;
|
||||
|
||||
private static Exception[] DownloadClientExceptions =
|
||||
{
|
||||
new DownloadClientUnavailableException("error"),
|
||||
new DownloadClientAuthenticationException("error"),
|
||||
new DownloadClientException("error")
|
||||
};
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_downloadItem = new DownloadClientItem
|
||||
{
|
||||
DownloadClientInfo = new DownloadClientItemClientInfo { Name = "Test" },
|
||||
DownloadId = "TestId",
|
||||
OutputPath = new OsPath(_downloadItemPath)
|
||||
};
|
||||
|
||||
_clientStatus = new DownloadClientInfo
|
||||
{
|
||||
IsLocalhost = true,
|
||||
OutputRootFolders = new List<OsPath> { new OsPath(_downloadRootPath) }
|
||||
};
|
||||
|
||||
_downloadClient = Mocker.GetMock<IDownloadClient>();
|
||||
_downloadClient.Setup(s => s.Definition)
|
||||
.Returns(new DownloadClientDefinition { Name = "Test" });
|
||||
|
||||
_downloadClient.Setup(s => s.GetItems())
|
||||
.Returns(new List<DownloadClientItem> { _downloadItem });
|
||||
|
||||
_downloadClient.Setup(s => s.GetStatus())
|
||||
.Returns(_clientStatus);
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Returns(new IDownloadClient[] { _downloadClient.Object });
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(s => s.EnableCompletedDownloadHandling)
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(x => x.FolderExists(It.IsAny<string>()))
|
||||
.Returns((string path) =>
|
||||
{
|
||||
Ensure.That(path, () => path).IsValidPath();
|
||||
return false;
|
||||
});
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(x => x.FileExists(It.IsAny<string>()))
|
||||
.Returns((string path) =>
|
||||
{
|
||||
Ensure.That(path, () => path).IsValidPath();
|
||||
return false;
|
||||
});
|
||||
|
||||
Mocker.GetMock<ILocalizationService>()
|
||||
.Setup(s => s.GetLocalizedString(It.IsAny<string>()))
|
||||
.Returns("Some Warning Message");
|
||||
}
|
||||
|
||||
private void GivenFolderExists(string folder)
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(x => x.FolderExists(folder))
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
private void GivenFileExists(string file)
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(x => x.FileExists(file))
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
private void GivenDocker()
|
||||
{
|
||||
Mocker.GetMock<IOsInfo>()
|
||||
.Setup(x => x.IsDocker)
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_if_setup_correctly()
|
||||
{
|
||||
GivenFolderExists(_downloadRootPath);
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_permissions_error_if_local_client_download_root_missing()
|
||||
{
|
||||
Subject.Check().ShouldBeError(wikiFragment: "permissions-error");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_mapping_error_if_remote_client_root_path_invalid()
|
||||
{
|
||||
_clientStatus.IsLocalhost = false;
|
||||
_clientStatus.OutputRootFolders = new List<OsPath> { new OsPath("An invalid path") };
|
||||
|
||||
Subject.Check().ShouldBeError(wikiFragment: "bad-remote-path-mapping");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_download_client_error_if_local_client_root_path_invalid()
|
||||
{
|
||||
_clientStatus.IsLocalhost = true;
|
||||
_clientStatus.OutputRootFolders = new List<OsPath> { new OsPath("An invalid path") };
|
||||
|
||||
Subject.Check().ShouldBeError(wikiFragment: "bad-download-client-settings");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_path_mapping_error_if_remote_client_download_root_missing()
|
||||
{
|
||||
_clientStatus.IsLocalhost = false;
|
||||
|
||||
Subject.Check().ShouldBeError(wikiFragment: "bad-remote-path-mapping");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource("DownloadClientExceptions")]
|
||||
public void should_return_ok_if_client_throws_downloadclientexception(Exception ex)
|
||||
{
|
||||
_downloadClient.Setup(s => s.GetStatus())
|
||||
.Throws(ex);
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
|
||||
ExceptionVerification.ExpectedErrors(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_docker_path_mapping_error_if_on_docker_and_root_missing()
|
||||
{
|
||||
GivenDocker();
|
||||
|
||||
Subject.Check().ShouldBeError(wikiFragment: "docker-bad-remote-path-mapping");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_on_episode_imported_event()
|
||||
{
|
||||
GivenFolderExists(_downloadRootPath);
|
||||
var importEvent = new EpisodeImportedEvent(new LocalEpisode(), new EpisodeFile(), new List<EpisodeFile>(), true, new DownloadClientItem());
|
||||
|
||||
Subject.Check(importEvent).ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_permissions_error_on_episode_import_failed_event_if_file_exists()
|
||||
{
|
||||
var localEpisode = new LocalEpisode
|
||||
{
|
||||
Path = Path.Combine(_downloadItemPath, "file.mkv")
|
||||
};
|
||||
GivenFileExists(localEpisode.Path);
|
||||
|
||||
var importEvent = new EpisodeImportFailedEvent(new Exception(), localEpisode, true, new DownloadClientItem());
|
||||
|
||||
Subject.Check(importEvent).ShouldBeError(wikiFragment: "permissions-error");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_permissions_error_on_episode_import_failed_event_if_folder_exists()
|
||||
{
|
||||
GivenFolderExists(_downloadItemPath);
|
||||
|
||||
var importEvent = new EpisodeImportFailedEvent(null, null, true, _downloadItem);
|
||||
|
||||
Subject.Check(importEvent).ShouldBeError(wikiFragment: "permissions-error");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_permissions_error_on_episode_import_failed_event_for_local_client_if_folder_does_not_exist()
|
||||
{
|
||||
var importEvent = new EpisodeImportFailedEvent(null, null, true, _downloadItem);
|
||||
|
||||
Subject.Check(importEvent).ShouldBeError(wikiFragment: "permissions-error");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_mapping_error_on_episode_import_failed_event_for_remote_client_if_folder_does_not_exist()
|
||||
{
|
||||
_clientStatus.IsLocalhost = false;
|
||||
var importEvent = new EpisodeImportFailedEvent(null, null, true, _downloadItem);
|
||||
|
||||
Subject.Check(importEvent).ShouldBeError(wikiFragment: "bad-remote-path-mapping");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_mapping_error_on_episode_import_failed_event_for_remote_client_if_path_invalid()
|
||||
{
|
||||
_clientStatus.IsLocalhost = false;
|
||||
_downloadItem.OutputPath = new OsPath("an invalid path");
|
||||
var importEvent = new EpisodeImportFailedEvent(null, null, true, _downloadItem);
|
||||
|
||||
Subject.Check(importEvent).ShouldBeError(wikiFragment: "bad-remote-path-mapping");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_download_client_error_on_episode_import_failed_event_for_remote_client_if_path_invalid()
|
||||
{
|
||||
_clientStatus.IsLocalhost = true;
|
||||
_downloadItem.OutputPath = new OsPath("an invalid path");
|
||||
var importEvent = new EpisodeImportFailedEvent(null, null, true, _downloadItem);
|
||||
|
||||
Subject.Check(importEvent).ShouldBeError(wikiFragment: "bad-download-client-settings");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_docker_mapping_error_on_episode_import_failed_event_inside_docker_if_folder_does_not_exist()
|
||||
{
|
||||
GivenDocker();
|
||||
|
||||
_clientStatus.IsLocalhost = false;
|
||||
var importEvent = new EpisodeImportFailedEvent(null, null, true, _downloadItem);
|
||||
|
||||
Subject.Check(importEvent).ShouldBeError(wikiFragment: "docker-bad-remote-path-mapping");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource("DownloadClientExceptions")]
|
||||
public void should_return_ok_on_import_failed_event_if_client_throws_downloadclientexception(Exception ex)
|
||||
{
|
||||
_downloadClient.Setup(s => s.GetStatus())
|
||||
.Throws(ex);
|
||||
|
||||
var importEvent = new EpisodeImportFailedEvent(null, null, true, _downloadItem);
|
||||
|
||||
Subject.Check(importEvent).ShouldBeOk();
|
||||
|
||||
ExceptionVerification.ExpectedErrors(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
|
@ -33,6 +34,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
// Only check clients not in failure status, those get another message
|
||||
var clients = _downloadClientProvider.GetDownloadClients();
|
||||
var rootFolders = _rootFolderService.All();
|
||||
|
||||
|
@ -42,7 +44,6 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
{
|
||||
var status = client.GetStatus();
|
||||
var folders = status.OutputRootFolders;
|
||||
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
if (rootFolders.Any(r => r.Path.PathEquals(folder.FullPath)))
|
||||
|
@ -55,6 +56,10 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
{
|
||||
_logger.Debug(ex, "Unable to communicate with {0}", client.Definition.Name);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_logger.Debug(ex, "Unable to communicate with {0}", client.Definition.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unknown error occurred in DownloadClientRootFolderCheck HealthCheck");
|
||||
|
|
|
@ -23,10 +23,10 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
{
|
||||
var jackettAllProviders = _providerFactory.All().Where(
|
||||
i => i.ConfigContract.Equals("TorznabSettings") &&
|
||||
((i.Settings as TorznabSettings).BaseUrl.Contains("/torznab/all/api") ||
|
||||
(i.Settings as TorznabSettings).BaseUrl.Contains("/api/v2.0/indexers/all/results/torznab") ||
|
||||
(i.Settings as TorznabSettings).ApiPath.Contains("/torznab/all/api") ||
|
||||
(i.Settings as TorznabSettings).ApiPath.Contains("/api/v2.0/indexers/all/results/torznab")));
|
||||
((i.Settings as TorznabSettings).BaseUrl.Contains("/torznab/all/api", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
(i.Settings as TorznabSettings).BaseUrl.Contains("/api/v2.0/indexers/all/results/torznab", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
(i.Settings as TorznabSettings).ApiPath.Contains("/torznab/all/api", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
(i.Settings as TorznabSettings).ApiPath.Contains("/api/v2.0/indexers/all/results/torznab", StringComparison.InvariantCultureIgnoreCase)));
|
||||
|
||||
if (jackettAllProviders.Empty())
|
||||
{
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients;
|
||||
using NzbDrone.Core.Localization;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.RemotePathMappings;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ModelEvent<RemotePathMapping>))]
|
||||
[CheckOn(typeof(EpisodeImportFailedEvent), CheckOnCondition.SuccessfulOnly)]
|
||||
public class RemotePathMappingCheck : HealthCheckBase, IProvideHealthCheck
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
private readonly IOsInfo _osInfo;
|
||||
|
||||
public RemotePathMappingCheck(IDiskProvider diskProvider,
|
||||
IProvideDownloadClient downloadClientProvider,
|
||||
IConfigService configService,
|
||||
IOsInfo osInfo,
|
||||
Logger logger)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_downloadClientProvider = downloadClientProvider;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
_osInfo = osInfo;
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
// We don't care about client folders if we are not handling completed files
|
||||
if (!_configService.EnableCompletedDownloadHandling)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
// Only check clients not in failure status, those get another message
|
||||
var clients = _downloadClientProvider.GetDownloadClients();
|
||||
|
||||
foreach (var client in clients)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = client.GetStatus();
|
||||
var folders = status.OutputRootFolders;
|
||||
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
if (!folder.IsValid)
|
||||
{
|
||||
if (!status.IsLocalhost)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Remote download client {0} places downloads in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.", client.Definition.Name, folder.FullPath, _osInfo.Name), "#bad-remote-path-mapping");
|
||||
}
|
||||
else if (_osInfo.IsDocker)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("You are using docker; download client {0} reported files in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.", client.Definition.Name, folder.FullPath, _osInfo.Name), "#docker-bad-remote-path-mapping");
|
||||
}
|
||||
else
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Local download client {0} places downloads in {1} but this is not a valid {2} path. Review your download client settings.", client.Definition.Name, folder.FullPath, _osInfo.Name), "#bad-download-client-settings");
|
||||
}
|
||||
}
|
||||
|
||||
if (!_diskProvider.FolderExists(folder.FullPath))
|
||||
{
|
||||
if (_osInfo.IsDocker)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("You are using docker; download client {0} places downloads in {1} but this directory does not appear to exist inside the container. Review your remote path mappings and container volume settings.", client.Definition.Name, folder.FullPath), "#docker-bad-remote-path-mapping");
|
||||
}
|
||||
else if (!status.IsLocalhost)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Remote download client {0} places downloads in {1} but this directory does not appear to exist. Likely missing or incorrect remote path mapping.", client.Definition.Name, folder.FullPath), "#bad-remote-path-mapping");
|
||||
}
|
||||
else
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Download client {0} places downloads in {1} but Sonarr cannot see this directory. You may need to adjust the folder's permissions.", client.Definition.Name, folder.FullPath), "#permissions-error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
{
|
||||
_logger.Debug(ex, "Unable to communicate with {0}", client.Definition.Name);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_logger.Debug(ex, "Unable to communicate with {0}", client.Definition.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unknown error occured in RemotePathMapping HealthCheck");
|
||||
}
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
public HealthCheck Check(IEvent message)
|
||||
{
|
||||
// We don't care about client folders if we are not handling completed files
|
||||
if (!_configService.EnableCompletedDownloadHandling)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
if (typeof(EpisodeImportFailedEvent).IsAssignableFrom(message.GetType()))
|
||||
{
|
||||
var failureMessage = (EpisodeImportFailedEvent)message;
|
||||
|
||||
// if we can see the file exists but the import failed then likely a permissions issue
|
||||
if (failureMessage.EpisodeInfo != null)
|
||||
{
|
||||
var episodePath = failureMessage.EpisodeInfo.Path;
|
||||
|
||||
if (_diskProvider.FileExists(episodePath))
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Sonarr can see but not access downloaded episode {0}. Likely permissions error.", episodePath), "#permissions-error");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the file doesn't exist but EpisodeInfo is not null then the message is coming from
|
||||
// ImportApprovedEpisodes and the file must have been removed part way through processing
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("File {0} was removed part way through processing.", episodePath), "#remote-path-file-removed");
|
||||
}
|
||||
}
|
||||
|
||||
// If the previous case did not match then the failure occured in DownloadedEpisodeImportService,
|
||||
// while trying to locate the files reported by the download client
|
||||
// Only check clients not in failure status, those get another message
|
||||
var client = _downloadClientProvider.GetDownloadClients().FirstOrDefault(x => x.Definition.Name == failureMessage.DownloadClientInfo.Name);
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var status = client.GetStatus();
|
||||
var dlpath = client?.GetItems().FirstOrDefault(x => x.DownloadId == failureMessage.DownloadId)?.OutputPath.FullPath;
|
||||
|
||||
// If dlpath is null then there's not much useful we can report. Give a generic message so
|
||||
// that the user realises something is wrong.
|
||||
if (dlpath.IsNullOrWhiteSpace())
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, "Sonarr failed to import (an) episode(s). Check your logs for details.", "#remote-path-import-failed");
|
||||
}
|
||||
|
||||
if (!dlpath.IsPathValid())
|
||||
{
|
||||
if (!status.IsLocalhost)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Remote download client {0} reported files in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.", client.Definition.Name, dlpath, _osInfo.Name), "#bad-remote-path-mapping");
|
||||
}
|
||||
else if (_osInfo.IsDocker)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("You are using docker; download client {0} reported files in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.", client.Definition.Name, dlpath, _osInfo.Name), "#docker-bad-remote-path-mapping");
|
||||
}
|
||||
else
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Local download client {0} reported files in {1} but this is not a valid {2} path. Review your download client settings.", client.Definition.Name, dlpath, _osInfo.Name), "#bad-download-client-settings");
|
||||
}
|
||||
}
|
||||
|
||||
if (_diskProvider.FolderExists(dlpath))
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Sonarr can see but not access download directory {0}. Likely permissions error.", dlpath), "#permissions-error");
|
||||
}
|
||||
|
||||
// if it's a remote client/docker, likely missing path mappings
|
||||
if (_osInfo.IsDocker)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Sonarr can see but not access download directory {0}. Likely permissions error.", client.Definition.Name, dlpath), "#docker-bad-remote-path-mapping");
|
||||
}
|
||||
else if (!status.IsLocalhost)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Remote download client {0} reported files in {1} but this directory does not appear to exist. Likely missing remote path mapping.", client.Definition.Name, dlpath), "#bad-remote-path-mapping");
|
||||
}
|
||||
else
|
||||
{
|
||||
// path mappings shouldn't be needed locally so probably a permissions issue
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Download client {0} reported files in {1} but Sonarr cannot see this directory. You may need to adjust the folder's permissions.", client.Definition.Name, dlpath), "#permissions-error");
|
||||
}
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
{
|
||||
_logger.Debug(ex, "Unable to communicate with {0}", client.Definition.Name);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_logger.Debug(ex, "Unable to communicate with {0}", client.Definition.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unknown error occured in RemotePathMapping HealthCheck");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
return Check();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
if (Math.Abs(result.DateTimeUtc.Subtract(systemTime).TotalDays) >= 1)
|
||||
{
|
||||
_logger.Error("System time mismatch. SystemTime: {0} Expected Time: {1}. Update system time", systemTime, result.DateTimeUtc);
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"System time is off by more than 1 day. Scheduled tasks may not run correctly until the time is corrected");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"System time is off by more than 1 day. Scheduled tasks may not run correctly until the time is corrected", "#system-time-off");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
|
|
|
@ -16,16 +16,19 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
private readonly IAppFolderInfo _appFolderInfo;
|
||||
private readonly ICheckUpdateService _checkUpdateService;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
private readonly IOsInfo _osInfo;
|
||||
|
||||
public UpdateCheck(IDiskProvider diskProvider,
|
||||
IAppFolderInfo appFolderInfo,
|
||||
ICheckUpdateService checkUpdateService,
|
||||
IConfigFileProvider configFileProvider)
|
||||
IConfigFileProvider configFileProvider,
|
||||
IOsInfo osInfo)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_appFolderInfo = appFolderInfo;
|
||||
_checkUpdateService = checkUpdateService;
|
||||
_configFileProvider = configFileProvider;
|
||||
_osInfo = osInfo;
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
|
@ -34,7 +37,8 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
var uiFolder = Path.Combine(startupFolder, "UI");
|
||||
|
||||
if ((OsInfo.IsWindows || _configFileProvider.UpdateAutomatically) &&
|
||||
_configFileProvider.UpdateMechanism == UpdateMechanism.BuiltIn)
|
||||
_configFileProvider.UpdateMechanism == UpdateMechanism.BuiltIn &&
|
||||
!_osInfo.IsDocker)
|
||||
{
|
||||
if (OsInfo.IsOsx && startupFolder.GetAncestorFolders().Contains("AppTranslocation"))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue