Skip to content

Commit c5bd8b2

Browse files
committed
Backups
New: Backup drone's database and configuration from the UI New: Download Backup files from the UI Fixed: Run a database backup before upgrade
1 parent d74e461 commit c5bd8b2

32 files changed

+552
-27
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ Generated_Code #added for RIA/Silverlight projects
8484
# Backup & report files from converting an old project file to a newer
8585
# Visual Studio version. Backup files are not needed, because we have git ;-)
8686
_UpgradeReport_Files/
87-
Backup*/
8887
UpgradeLog*.XML
8988

9089
# SQL Server files
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.IO;
2+
using NLog;
3+
using NzbDrone.Common;
4+
using NzbDrone.Common.Disk;
5+
using NzbDrone.Common.EnvironmentInfo;
6+
7+
namespace NzbDrone.Api.Frontend.Mappers
8+
{
9+
public class BackupFileMapper : StaticResourceMapperBase
10+
{
11+
private readonly IAppFolderInfo _appFolderInfo;
12+
13+
public BackupFileMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, Logger logger)
14+
: base(diskProvider, logger)
15+
{
16+
_appFolderInfo = appFolderInfo;
17+
}
18+
19+
protected override string Map(string resourceUrl)
20+
{
21+
var path = resourceUrl.Replace("/backup/", "").Replace('/', Path.DirectorySeparatorChar);
22+
23+
return Path.Combine(_appFolderInfo.GetBackupFolder(), path);
24+
}
25+
26+
public override bool CanHandle(string resourceUrl)
27+
{
28+
return resourceUrl.StartsWith("/backup/") && resourceUrl.ContainsIgnoreCase("nzbdrone_backup_") && resourceUrl.EndsWith(".zip");
29+
}
30+
}
31+
}

src/NzbDrone.Api/NzbDrone.Api.csproj

+3
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
<Compile Include="Extensions\RequestExtensions.cs" />
132132
<Compile Include="Frontend\IsCacheableSpecification.cs" />
133133
<Compile Include="Frontend\Mappers\UpdateLogFileMapper.cs" />
134+
<Compile Include="Frontend\Mappers\BackupFileMapper.cs" />
134135
<Compile Include="Frontend\Mappers\FaviconMapper.cs" />
135136
<Compile Include="Frontend\Mappers\IndexHtmlMapper.cs" />
136137
<Compile Include="Frontend\Mappers\LogFileMapper.cs" />
@@ -165,6 +166,8 @@
165166
<Compile Include="Mapping\ResourceMappingException.cs" />
166167
<Compile Include="Mapping\ValueInjectorExtensions.cs" />
167168
<Compile Include="Series\AlternateTitleResource.cs" />
169+
<Compile Include="System\Backup\BackupModule.cs" />
170+
<Compile Include="System\Backup\BackupResource.cs" />
168171
<Compile Include="Update\UpdateResource.cs" />
169172
<Compile Include="Wanted\CutoffModule.cs" />
170173
<Compile Include="Wanted\LegacyMissingModule.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Linq;
4+
using NzbDrone.Core.Backup;
5+
6+
namespace NzbDrone.Api.System.Backup
7+
{
8+
public class BackupModule : NzbDroneRestModule<BackupResource>
9+
{
10+
private readonly IBackupService _backupService;
11+
12+
public BackupModule(IBackupService backupService) : base("system/backup")
13+
{
14+
_backupService = backupService;
15+
GetResourceAll = GetBackupFiles;
16+
}
17+
18+
public List<BackupResource> GetBackupFiles()
19+
{
20+
var backups = _backupService.GetBackups();
21+
22+
return backups.Select(b => new BackupResource
23+
{
24+
Id = b.Path.GetHashCode(),
25+
Name = Path.GetFileName(b.Path),
26+
Path = b.Path,
27+
Type = b.Type,
28+
Time = b.Time
29+
}).ToList();
30+
}
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using NzbDrone.Api.REST;
3+
using NzbDrone.Core.Backup;
4+
5+
namespace NzbDrone.Api.System.Backup
6+
{
7+
public class BackupResource : RestResource
8+
{
9+
public String Name { get; set; }
10+
public String Path { get; set; }
11+
public BackupType Type { get; set; }
12+
public DateTime Time { get; set; }
13+
}
14+
}

src/NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixtureBase.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public void should_be_able_to_delete_directory_with_read_only_file()
172172
public void empty_folder_should_return_folder_modified_date()
173173
{
174174
var tempfolder = new DirectoryInfo(TempFolder);
175-
Subject.FolderGetLastWrite(TempFolder).Should().Be(tempfolder.LastWriteTimeUtc);
175+
Subject.FolderGetLastWriteUtc(TempFolder).Should().Be(tempfolder.LastWriteTimeUtc);
176176
}
177177

178178
[Test]
@@ -189,8 +189,8 @@ public void folder_should_return_correct_value_for_last_write()
189189

190190
Subject.WriteAllText(testFile, "Test");
191191

192-
Subject.FolderGetLastWrite(TempFolder).Should().BeOnOrAfter(DateTime.UtcNow.AddMinutes(-1));
193-
Subject.FolderGetLastWrite(TempFolder).Should().BeBefore(DateTime.UtcNow.AddMinutes(1));
192+
Subject.FolderGetLastWriteUtc(TempFolder).Should().BeOnOrAfter(DateTime.UtcNow.AddMinutes(-1));
193+
Subject.FolderGetLastWriteUtc(TempFolder).Should().BeBefore(DateTime.UtcNow.AddMinutes(1));
194194
}
195195

196196
[Test]
@@ -238,7 +238,7 @@ public void should_be_able_to_set_permission_from_parrent()
238238
[Explicit]
239239
public void check_last_write()
240240
{
241-
Console.WriteLine(Subject.FolderGetLastWrite(GetFilledTempFolder().FullName));
241+
Console.WriteLine(Subject.FolderGetLastWriteUtc(GetFilledTempFolder().FullName));
242242
Console.WriteLine(GetFilledTempFolder().LastWriteTimeUtc);
243243
}
244244

src/NzbDrone.Common/ArchiveProvider.cs src/NzbDrone.Common/ArchiveService.cs

+18-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace NzbDrone.Common
1212
public interface IArchiveService
1313
{
1414
void Extract(string compressedFile, string destination);
15+
void ExtractZip(string compressedFile, string destination);
16+
void CreateZip(string path, params string[] files);
1517
}
1618

1719
public class ArchiveService : IArchiveService
@@ -40,7 +42,22 @@ public void Extract(string compressedFile, string destination)
4042
_logger.Debug("Extraction complete.");
4143
}
4244

43-
private void ExtractZip(string compressedFile, string destination)
45+
public void CreateZip(string path, params string[] files)
46+
{
47+
using (var zipFile = ZipFile.Create(path))
48+
{
49+
zipFile.BeginUpdate();
50+
51+
foreach (var file in files)
52+
{
53+
zipFile.Add(file, Path.GetFileName(file));
54+
}
55+
56+
zipFile.CommitUpdate();
57+
}
58+
}
59+
60+
public void ExtractZip(string compressedFile, string destination)
4461
{
4562
using (var fileStream = File.OpenRead(compressedFile))
4663
{

src/NzbDrone.Common/Disk/DiskProviderBase.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public DateTime FolderGetCreationTimeUtc(string path)
3333
return new DirectoryInfo(path).CreationTimeUtc;
3434
}
3535

36-
public DateTime FolderGetLastWrite(string path)
36+
public DateTime FolderGetLastWriteUtc(string path)
3737
{
3838
CheckFolderExists(path);
3939

src/NzbDrone.Common/Disk/IDiskProvider.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public interface IDiskProvider
1212
void SetPermissions(string path, string mask, string user, string group);
1313
long? GetTotalSize(string path);
1414
DateTime FolderGetCreationTimeUtc(string path);
15-
DateTime FolderGetLastWrite(string path);
15+
DateTime FolderGetLastWriteUtc(string path);
1616
DateTime FileGetCreationTimeUtc(string path);
1717
DateTime FileGetLastWrite(string path);
1818
DateTime FileGetLastWriteUtc(string path);

src/NzbDrone.Common/NzbDrone.Common.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@
5959
</Reference>
6060
</ItemGroup>
6161
<ItemGroup>
62-
<Compile Include="ArchiveProvider.cs" />
6362
<Compile Include="ConvertBase32.cs" />
63+
<Compile Include="ArchiveService.cs" />
6464
<Compile Include="Cache\Cached.cs" />
6565
<Compile Include="Cache\CacheManager.cs" />
6666
<Compile Include="Cache\ICached.cs" />

src/NzbDrone.Common/PathExtensions.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ public static class PathExtensions
1111
private const string APP_CONFIG_FILE = "config.xml";
1212
private const string NZBDRONE_DB = "nzbdrone.db";
1313
private const string NZBDRONE_LOG_DB = "logs.db";
14-
private const string BACKUP_ZIP_FILE = "NzbDrone_Backup.zip";
1514
private const string NLOG_CONFIG_FILE = "nlog.config";
1615
private const string UPDATE_CLIENT_EXE = "NzbDrone.Update.exe";
16+
private const string BACKUP_FOLDER = "Backups";
1717

1818
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "nzbdrone_update" + Path.DirectorySeparatorChar;
1919
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "NzbDrone" + Path.DirectorySeparatorChar;
@@ -226,9 +226,9 @@ public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo)
226226
return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE);
227227
}
228228

229-
public static string GetConfigBackupFile(this IAppFolderInfo appFolderInfo)
229+
public static string GetBackupFolder(this IAppFolderInfo appFolderInfo)
230230
{
231-
return Path.Combine(GetAppDataPath(appFolderInfo), BACKUP_ZIP_FILE);
231+
return Path.Combine(GetAppDataPath(appFolderInfo), BACKUP_FOLDER);
232232
}
233233

234234
public static string GetNzbDroneDatabase(this IAppFolderInfo appFolderInfo)

src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class CleanupFixture : CoreTest
1818

1919
private void WithExpired()
2020
{
21-
Mocker.GetMock<IDiskProvider>().Setup(s => s.FolderGetLastWrite(It.IsAny<String>()))
21+
Mocker.GetMock<IDiskProvider>().Setup(s => s.FolderGetLastWriteUtc(It.IsAny<String>()))
2222
.Returns(DateTime.UtcNow.AddDays(-10));
2323

2424
Mocker.GetMock<IDiskProvider>().Setup(s => s.FileGetLastWriteUtc(It.IsAny<String>()))
@@ -27,7 +27,7 @@ private void WithExpired()
2727

2828
private void WithNonExpired()
2929
{
30-
Mocker.GetMock<IDiskProvider>().Setup(s => s.FolderGetLastWrite(It.IsAny<String>()))
30+
Mocker.GetMock<IDiskProvider>().Setup(s => s.FolderGetLastWriteUtc(It.IsAny<String>()))
3131
.Returns(DateTime.UtcNow.AddDays(-3));
3232

3333
Mocker.GetMock<IDiskProvider>().Setup(s => s.FileGetLastWriteUtc(It.IsAny<String>()))

src/NzbDrone.Core/Backup/Backup.cs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace NzbDrone.Core.Backup
4+
{
5+
public class Backup
6+
{
7+
public String Path { get; set; }
8+
public BackupType Type { get; set; }
9+
public DateTime Time { get; set; }
10+
}
11+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using NzbDrone.Core.Messaging.Commands;
2+
3+
namespace NzbDrone.Core.Backup
4+
{
5+
public class BackupCommand : Command
6+
{
7+
public BackupType Type { get; set; }
8+
9+
public override bool SendUpdatesToClient
10+
{
11+
get
12+
{
13+
return true;
14+
}
15+
}
16+
}
17+
18+
public enum BackupType
19+
{
20+
Scheduled = 0 ,
21+
Manual = 1,
22+
Update = 2
23+
}
24+
}

0 commit comments

Comments
 (0)