mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-14 00:53:57 -07:00
A remote path mapping health check (#617)
This commit is contained in:
parent
0762805572
commit
e27369686b
12 changed files with 360 additions and 15 deletions
|
@ -27,6 +27,7 @@ function getInternalLink(source) {
|
||||||
);
|
);
|
||||||
case 'DownloadClientCheck':
|
case 'DownloadClientCheck':
|
||||||
case 'ImportMechanismCheck':
|
case 'ImportMechanismCheck':
|
||||||
|
case 'RemotePathMappingCheck':
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.SETTINGS}
|
name={icons.SETTINGS}
|
||||||
|
|
|
@ -14,7 +14,8 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||||
public static bool IsLinux => Os == Os.Linux;
|
public static bool IsLinux => Os == Os.Linux;
|
||||||
public static bool IsOsx => Os == Os.Osx;
|
public static bool IsOsx => Os == Os.Osx;
|
||||||
public static bool IsWindows => Os == Os.Windows;
|
public static bool IsWindows => Os == Os.Windows;
|
||||||
|
public static bool IsDocker { get; }
|
||||||
|
|
||||||
public string Version { get; }
|
public string Version { get; }
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string FullName { get; }
|
public string FullName { get; }
|
||||||
|
@ -44,6 +45,10 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Os = Os.Linux;
|
Os = Os.Linux;
|
||||||
|
if (File.Exists("/proc/1/cgroup") && File.ReadAllText("/proc/1/cgroup").Contains("/docker/"))
|
||||||
|
{
|
||||||
|
IsDocker = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -101,4 +106,4 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||||
Linux,
|
Linux,
|
||||||
Osx
|
Osx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,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);
|
result.Type.Should().Be(HealthCheckResult.Error);
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||||
{
|
{
|
||||||
result.Message.Should().Contain(message);
|
result.Message.Should().Contain(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wikiFragment.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
result.WikiUrl.Fragment.Should().Be(wikiFragment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.HealthCheck.Checks;
|
||||||
|
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;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
downloadItem = new DownloadClientItem {
|
||||||
|
DownloadClient = "Test",
|
||||||
|
DownloadId = "TestId",
|
||||||
|
OutputPath = new OsPath(downloadItemPath)
|
||||||
|
};
|
||||||
|
|
||||||
|
clientStatus = new DownloadClientInfo {
|
||||||
|
IsLocalhost = true,
|
||||||
|
OutputRootFolders = new List<OsPath> { new OsPath(downloadRootPath) }
|
||||||
|
};
|
||||||
|
|
||||||
|
var 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<IDiskProvider>()
|
||||||
|
.Setup(x => x.FolderExists(It.IsAny<string>()))
|
||||||
|
.Returns(false);
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(x => x.FileExists(It.IsAny<string>()))
|
||||||
|
.Returns(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
[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_path_mapping_error_if_remote_client_download_root_missing()
|
||||||
|
{
|
||||||
|
clientStatus.IsLocalhost = false;
|
||||||
|
|
||||||
|
Subject.Check().ShouldBeError(wikiFragment: "bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Explicit("Only works if running inside a docker container")]
|
||||||
|
public void should_return_docker_path_mapping_error_if_on_docker_and_root_missing()
|
||||||
|
{
|
||||||
|
Subject.Check().ShouldBeError(wikiFragment: "docker-bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_ok_on_track_imported_event()
|
||||||
|
{
|
||||||
|
GivenFolderExists(downloadRootPath);
|
||||||
|
var importEvent = new TrackImportedEvent(new LocalTrack(), new TrackFile(), new List<TrackFile>(), true, new DownloadClientItem());
|
||||||
|
|
||||||
|
Subject.Check(importEvent).ShouldBeOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_permissions_error_on_track_import_failed_event_if_file_exists()
|
||||||
|
{
|
||||||
|
var localTrack = new LocalTrack {
|
||||||
|
Path = Path.Combine(downloadItemPath, "file.mp3")
|
||||||
|
};
|
||||||
|
GivenFileExists(localTrack.Path);
|
||||||
|
|
||||||
|
var importEvent = new TrackImportFailedEvent(new Exception(), localTrack, true, new DownloadClientItem());
|
||||||
|
|
||||||
|
Subject.Check(importEvent).ShouldBeError(wikiFragment: "permissions-error");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_permissions_error_on_track_import_failed_event_if_folder_exists()
|
||||||
|
{
|
||||||
|
GivenFolderExists(downloadItemPath);
|
||||||
|
|
||||||
|
var importEvent = new TrackImportFailedEvent(null, null, true, downloadItem);
|
||||||
|
|
||||||
|
Subject.Check(importEvent).ShouldBeError(wikiFragment: "permissions-error");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_permissions_error_on_track_import_failed_event_for_local_client_if_folder_does_not_exist()
|
||||||
|
{
|
||||||
|
var importEvent = new TrackImportFailedEvent(null, null, true, downloadItem);
|
||||||
|
|
||||||
|
Subject.Check(importEvent).ShouldBeError(wikiFragment: "permissions-error");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_mapping_error_on_track_import_failed_event_for_remote_client_if_folder_does_not_exist()
|
||||||
|
{
|
||||||
|
clientStatus.IsLocalhost = false;
|
||||||
|
var importEvent = new TrackImportFailedEvent(null, null, true, downloadItem);
|
||||||
|
|
||||||
|
Subject.Check(importEvent).ShouldBeError(wikiFragment: "bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Explicit("Only works if running inside a docker container")]
|
||||||
|
public void should_return_docker_mapping_error_on_track_import_failed_event_inside_docker_if_folder_does_not_exist()
|
||||||
|
{
|
||||||
|
clientStatus.IsLocalhost = false;
|
||||||
|
var importEvent = new TrackImportFailedEvent(null, null, true, downloadItem);
|
||||||
|
|
||||||
|
Subject.Check(importEvent).ShouldBeError(wikiFragment: "docker-bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -224,6 +224,7 @@
|
||||||
<Compile Include="HealthCheck\Checks\IndexerStatusCheckFixture.cs" />
|
<Compile Include="HealthCheck\Checks\IndexerStatusCheckFixture.cs" />
|
||||||
<Compile Include="HealthCheck\Checks\RootFolderCheckFixture.cs" />
|
<Compile Include="HealthCheck\Checks\RootFolderCheckFixture.cs" />
|
||||||
<Compile Include="HealthCheck\Checks\UpdateCheckFixture.cs" />
|
<Compile Include="HealthCheck\Checks\UpdateCheckFixture.cs" />
|
||||||
|
<Compile Include="HealthCheck\Checks\RemotePathMappingCheckFixture.cs" />
|
||||||
<Compile Include="HealthCheck\HealthCheckFixture.cs" />
|
<Compile Include="HealthCheck\HealthCheckFixture.cs" />
|
||||||
<Compile Include="HistoryTests\HistoryRepositoryFixture.cs" />
|
<Compile Include="HistoryTests\HistoryRepositoryFixture.cs" />
|
||||||
<Compile Include="HistoryTests\HistoryServiceFixture.cs" />
|
<Compile Include="HistoryTests\HistoryServiceFixture.cs" />
|
||||||
|
|
128
src/NzbDrone.Core/HealthCheck/Checks/RemotePathMappingCheck.cs
Normal file
128
src/NzbDrone.Core/HealthCheck/Checks/RemotePathMappingCheck.cs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using NzbDrone.Core.Datastore.Events;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
using NzbDrone.Core.RemotePathMappings;
|
||||||
|
using NzbDrone.Core.ThingiProvider.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.HealthCheck.Checks
|
||||||
|
{
|
||||||
|
[CheckOn(typeof(ProviderAddedEvent<IDownloadClient>))]
|
||||||
|
[CheckOn(typeof(ProviderUpdatedEvent<IDownloadClient>))]
|
||||||
|
[CheckOn(typeof(ProviderDeletedEvent<IDownloadClient>))]
|
||||||
|
[CheckOn(typeof(ModelEvent<RemotePathMapping>))]
|
||||||
|
[CheckOn(typeof(TrackImportedEvent), CheckOnCondition.FailedOnly)]
|
||||||
|
[CheckOn(typeof(TrackImportFailedEvent), CheckOnCondition.SuccessfulOnly)]
|
||||||
|
public class RemotePathMappingCheck : HealthCheckBase, IProvideHealthCheckWithMessage
|
||||||
|
{
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public RemotePathMappingCheck(IDiskProvider diskProvider,
|
||||||
|
IProvideDownloadClient downloadClientProvider,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_downloadClientProvider = downloadClientProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HealthCheck Check()
|
||||||
|
{
|
||||||
|
var clients = _downloadClientProvider.GetDownloadClients();
|
||||||
|
|
||||||
|
foreach (var client in clients)
|
||||||
|
{
|
||||||
|
var folders = client.GetStatus().OutputRootFolders;
|
||||||
|
if (folders != null)
|
||||||
|
{
|
||||||
|
foreach (var folder in folders)
|
||||||
|
{
|
||||||
|
if (!_diskProvider.FolderExists(folder.FullPath))
|
||||||
|
{
|
||||||
|
if (OsInfo.IsDocker)
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"You are using docker; download client {client.Definition.Name} places downloads in {folder.FullPath} but this directory does not appear to exist inside the container. Review your remote path mappings and container volume settings.", "#docker-bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
else if (!client.GetStatus().IsLocalhost)
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Remote download client {client.Definition.Name} places downloads in {folder.FullPath} but this directory does not appear to exist. Likely missing or incorrect remote path mapping.", "#bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Download client {client.Definition.Name} places downloads in {folder.FullPath} but Lidarr cannot see this directory. You may need to adjust the folder's permissions.", "#permissions-error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new HealthCheck(GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public HealthCheck Check(IEvent message)
|
||||||
|
{
|
||||||
|
if (typeof(TrackImportFailedEvent).IsAssignableFrom(message.GetType()))
|
||||||
|
{
|
||||||
|
var failureMessage = (TrackImportFailedEvent) message;
|
||||||
|
|
||||||
|
// if we can see the file exists but the import failed then likely a permissions issue
|
||||||
|
if (failureMessage.TrackInfo != null)
|
||||||
|
{
|
||||||
|
var trackPath = failureMessage.TrackInfo.Path;
|
||||||
|
if (_diskProvider.FileExists(trackPath))
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Lidarr can see but not access downloaded track {trackPath}. Likely permissions error.", "#permissions-error");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the file doesn't exist but TrackInfo is not null then the message is coming from
|
||||||
|
// ImportApprovedTracks and the file must have been removed part way through processing
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"File {trackPath} was removed part way though procesing.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the previous case did not match then the failure occured in DownloadedTracksImportService,
|
||||||
|
// while trying to locate the files reported by the download client
|
||||||
|
var client = _downloadClientProvider.GetDownloadClients().FirstOrDefault(x => x.Definition.Name == failureMessage.DownloadClient);
|
||||||
|
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, $"Lidarr failed to import a track. Check your logs for details.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_diskProvider.FolderExists(dlpath))
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Lidarr can see but not access download directory {dlpath}. Likely permissions error.", "#permissions-error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's a remote client/docker, likely missing path mappings
|
||||||
|
if (OsInfo.IsDocker)
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"You are using docker; download client {client.Definition.Name} reported files in {dlpath} but this directory does not appear to exist inside the container. Review your remote path mappings and container volume settings.", "#docker-bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
else if (!client.GetStatus().IsLocalhost)
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Remote download client {client.Definition.Name} reported files in {dlpath} but this directory does not appear to exist. Likely missing remote path mapping.", "#bad-remote-path-mapping");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// path mappings shouldn't be needed locally so probably a permissions issue
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Download client {client.Definition.Name} reported files in {dlpath} but Lidarr cannot see this directory. You may need to adjust the folder's permissions.", "#permissions-error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Check();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,10 +66,21 @@ namespace NzbDrone.Core.HealthCheck
|
||||||
.ToDictionary(g => g.Key, g => g.ToArray());
|
.ToDictionary(g => g.Key, g => g.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PerformHealthCheck(IProvideHealthCheck[] healthChecks)
|
private void PerformHealthCheck(IProvideHealthCheck[] healthChecks, IEvent message = null)
|
||||||
{
|
{
|
||||||
var results = healthChecks.Select(c => c.Check())
|
var results = new List<HealthCheck>();
|
||||||
.ToList();
|
|
||||||
|
foreach (var healthCheck in healthChecks)
|
||||||
|
{
|
||||||
|
if (healthCheck is IProvideHealthCheckWithMessage && message != null)
|
||||||
|
{
|
||||||
|
results.Add(((IProvideHealthCheckWithMessage)healthCheck).Check(message));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
results.Add(healthCheck.Check());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var result in results)
|
foreach (var result in results)
|
||||||
{
|
{
|
||||||
|
@ -151,8 +162,7 @@ namespace NzbDrone.Core.HealthCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add debounce
|
// TODO: Add debounce
|
||||||
|
PerformHealthCheck(filteredChecks.ToArray(), message);
|
||||||
PerformHealthCheck(filteredChecks.ToArray());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.HealthCheck
|
namespace NzbDrone.Core.HealthCheck
|
||||||
{
|
{
|
||||||
public interface IProvideHealthCheck
|
public interface IProvideHealthCheck
|
||||||
|
@ -6,4 +8,9 @@ namespace NzbDrone.Core.HealthCheck
|
||||||
bool CheckOnStartup { get; }
|
bool CheckOnStartup { get; }
|
||||||
bool CheckOnSchedule { get; }
|
bool CheckOnSchedule { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IProvideHealthCheckWithMessage : IProvideHealthCheck
|
||||||
|
{
|
||||||
|
HealthCheck Check(IEvent message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,9 @@ using NLog;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.MediaFiles.TrackImport;
|
using NzbDrone.Core.MediaFiles.TrackImport;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Music;
|
using NzbDrone.Core.Music;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
@ -28,15 +30,17 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
private readonly IParsingService _parsingService;
|
private readonly IParsingService _parsingService;
|
||||||
private readonly IMakeImportDecision _importDecisionMaker;
|
private readonly IMakeImportDecision _importDecisionMaker;
|
||||||
private readonly IImportApprovedTracks _importApprovedTracks;
|
private readonly IImportApprovedTracks _importApprovedTracks;
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public DownloadedTracksImportService(IDiskProvider diskProvider,
|
public DownloadedTracksImportService(IDiskProvider diskProvider,
|
||||||
IDiskScanService diskScanService,
|
IDiskScanService diskScanService,
|
||||||
IArtistService artistService,
|
IArtistService artistService,
|
||||||
IParsingService parsingService,
|
IParsingService parsingService,
|
||||||
IMakeImportDecision importDecisionMaker,
|
IMakeImportDecision importDecisionMaker,
|
||||||
IImportApprovedTracks importApprovedTracks,
|
IImportApprovedTracks importApprovedTracks,
|
||||||
Logger logger)
|
IEventAggregator eventAggregator,
|
||||||
|
Logger logger)
|
||||||
{
|
{
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_diskScanService = diskScanService;
|
_diskScanService = diskScanService;
|
||||||
|
@ -44,6 +48,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
_parsingService = parsingService;
|
_parsingService = parsingService;
|
||||||
_importDecisionMaker = importDecisionMaker;
|
_importDecisionMaker = importDecisionMaker;
|
||||||
_importApprovedTracks = importApprovedTracks;
|
_importApprovedTracks = importApprovedTracks;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +98,8 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Error("Import failed, path does not exist or is not accessible by Lidarr: {0}", path);
|
_logger.Error("Import failed, path does not exist or is not accessible by Lidarr: {0}", path);
|
||||||
|
_eventAggregator.PublishEvent(new TrackImportFailedEvent(null, null, true, downloadClientItem));
|
||||||
|
|
||||||
return new List<ImportResult>();
|
return new List<ImportResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -231,6 +231,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||||
catch (UnauthorizedAccessException e)
|
catch (UnauthorizedAccessException e)
|
||||||
{
|
{
|
||||||
_logger.Warn(e, "Couldn't import track " + localTrack);
|
_logger.Warn(e, "Couldn't import track " + localTrack);
|
||||||
|
_eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, !localTrack.ExistingFile, downloadClientItem));
|
||||||
|
|
||||||
importResults.Add(new ImportResult(importDecision, "Failed to import track, Permissions error"));
|
importResults.Add(new ImportResult(importDecision, "Failed to import track, Permissions error"));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
@ -504,6 +504,7 @@
|
||||||
<Compile Include="HealthCheck\Checks\IndexerSearchCheck.cs" />
|
<Compile Include="HealthCheck\Checks\IndexerSearchCheck.cs" />
|
||||||
<Compile Include="HealthCheck\Checks\MonoVersionCheck.cs" />
|
<Compile Include="HealthCheck\Checks\MonoVersionCheck.cs" />
|
||||||
<Compile Include="HealthCheck\Checks\ProxyCheck.cs" />
|
<Compile Include="HealthCheck\Checks\ProxyCheck.cs" />
|
||||||
|
<Compile Include="HealthCheck\Checks\RemotePathMappingCheck.cs" />
|
||||||
<Compile Include="HealthCheck\Checks\RootFolderCheck.cs" />
|
<Compile Include="HealthCheck\Checks\RootFolderCheck.cs" />
|
||||||
<Compile Include="HealthCheck\Checks\UpdateCheck.cs" />
|
<Compile Include="HealthCheck\Checks\UpdateCheck.cs" />
|
||||||
<Compile Include="HealthCheck\EventDrivenHealthCheck.cs" />
|
<Compile Include="HealthCheck\EventDrivenHealthCheck.cs" />
|
||||||
|
|
|
@ -16,6 +16,13 @@ namespace NzbDrone.Core.RemotePathMappings
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public new void Delete(int id)
|
||||||
|
{
|
||||||
|
var model = Get(id);
|
||||||
|
base.Delete(id);
|
||||||
|
ModelDeleted(model);
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool PublishModelEvents => true;
|
protected override bool PublishModelEvents => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue