Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/duplicati/duplicati.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Skovhede <kenneth@hexad.dk>2014-10-14 16:45:49 +0400
committerKenneth Skovhede <kenneth@hexad.dk>2014-10-14 16:45:49 +0400
commitc2fc930411ddbcd15072acc9d68f7c6be06ea451 (patch)
tree1464e18f89e269164ae036fd9592ea7f6e9d12c8 /Duplicati
parentd5dd9391f3bf01238ef6191b72e921602e63fa3d (diff)
Implemented storing backup task info in the backup data
Diffstat (limited to 'Duplicati')
-rw-r--r--Duplicati/Server/Database/Connection.cs14
-rw-r--r--Duplicati/Server/Duplicati.Server.csproj1
-rw-r--r--Duplicati/Server/Runner.cs52
-rw-r--r--Duplicati/Server/Serializable/ImportExportStructure.cs33
-rw-r--r--Duplicati/Server/SpecialFolders.cs28
-rw-r--r--Duplicati/Server/WebServer/ControlHandler.cs25
-rw-r--r--Duplicati/Server/WebServer/ControlMethods/GetBackup.cs30
-rw-r--r--Duplicati/Server/webroot/greeno/index.html12
-rw-r--r--Duplicati/Server/webroot/greeno/scripts/editdialog.js3
9 files changed, 145 insertions, 53 deletions
diff --git a/Duplicati/Server/Database/Connection.cs b/Duplicati/Server/Database/Connection.cs
index ec5416f0d..12c5087fe 100644
--- a/Duplicati/Server/Database/Connection.cs
+++ b/Duplicati/Server/Database/Connection.cs
@@ -64,7 +64,18 @@ namespace Duplicati.Server.Database
using(var cmd = m_connection.CreateCommand())
f(cmd);
}
-
+
+ internal Serializable.ImportExportStructure PrepareBackupForExport(IBackup backup)
+ {
+ var scheduleId = GetScheduleIDsFromTags(new string[] { "ID=" + backup.ID });
+ return new Serializable.ImportExportStructure() {
+ CreatedByVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(),
+ Backup = (Database.Backup)backup,
+ Schedule = (Database.Schedule)(scheduleId.Any() ? GetSchedule(scheduleId.First()) : null),
+ DisplayNames = SpecialFolders.GetSourceNames(backup)
+ };
+ }
+
public string RegisterTemporaryBackup(IBackup backup)
{
lock(m_lock)
@@ -562,6 +573,7 @@ namespace Duplicati.Server.Database
foreach(var n in lst)
n.Metadata = GetMetadata(long.Parse(n.ID));
+
return lst;
}
}
diff --git a/Duplicati/Server/Duplicati.Server.csproj b/Duplicati/Server/Duplicati.Server.csproj
index df9b5dca3..00239723b 100644
--- a/Duplicati/Server/Duplicati.Server.csproj
+++ b/Duplicati/Server/Duplicati.Server.csproj
@@ -119,6 +119,7 @@
<Compile Include="LogWriteHandler.cs" />
<Compile Include="Database\Notification.cs" />
<Compile Include="Database\TempFile.cs" />
+ <Compile Include="Serializable\ImportExportStructure.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
diff --git a/Duplicati/Server/Runner.cs b/Duplicati/Server/Runner.cs
index 41fa9bad5..9518aa41e 100644
--- a/Duplicati/Server/Runner.cs
+++ b/Duplicati/Server/Runner.cs
@@ -325,6 +325,7 @@ namespace Duplicati.Server
public static Duplicati.Library.Interface.IBasicResults Run(IRunnerData data, bool fromQueue)
{
var backup = data.Backup;
+ Duplicati.Library.Utility.TempFolder tempfolder = null;
if (backup.Metadata == null)
backup.Metadata = new Dictionary<string, string>();
@@ -342,7 +343,10 @@ namespace Duplicati.Server
if (data.ExtraOptions != null)
foreach(var k in data.ExtraOptions)
options[k.Key] = k.Value;
-
+
+ // Log file is using the internal log-handler
+ // so we can display output in the GUI as well as log
+ // into the given file
if (options.ContainsKey("log-file"))
{
var file = options["log-file"];
@@ -357,7 +361,49 @@ namespace Duplicati.Server
Program.LogHandler.SetOperationFile(file, level);
}
-
+
+ // Pack in the system or task config for easy restore
+ if (data.Operation == DuplicatiOperation.Backup && options.ContainsKey("store-task-config"))
+ {
+ var all_tasks = string.Equals(options["store-task-config"], "all", StringComparison.InvariantCultureIgnoreCase) || string.Equals(options["store-task-config"], "*", StringComparison.InvariantCultureIgnoreCase);
+ var this_task = Duplicati.Library.Utility.Utility.ParseBool(options["store-task-config"], false);
+
+ options.Remove("store-task-config");
+
+ if (all_tasks || this_task)
+ {
+ if (tempfolder == null)
+ tempfolder = new Duplicati.Library.Utility.TempFolder();
+
+ var temppath = System.IO.Path.Combine(tempfolder, "task-setup.json");
+ using(var tempfile = Duplicati.Library.Utility.TempFile.WrapExistingFile(temppath))
+ {
+ object taskdata = null;
+ if (all_tasks)
+ taskdata = Program.DataConnection.Backups.Where(x => !x.IsTemporary).Select(x => Program.DataConnection.PrepareBackupForExport(Program.DataConnection.GetBackup(x.ID)));
+ else
+ taskdata = new [] { Program.DataConnection.PrepareBackupForExport(data.Backup) };
+
+ using(var fs = System.IO.File.OpenWrite(tempfile))
+ using(var sw = new System.IO.StreamWriter(fs, System.Text.Encoding.UTF8))
+ Serializer.SerializeJson(sw, taskdata, true);
+
+ tempfile.Protected = true;
+
+ string controlfiles = null;
+ options.TryGetValue("control-files", out controlfiles);
+
+ if (string.IsNullOrWhiteSpace(controlfiles))
+ controlfiles = tempfile;
+ else
+ controlfiles += System.IO.Path.PathSeparator + tempfile;
+
+ options["control-files"] = controlfiles;
+ }
+ }
+ }
+
+ using(tempfolder)
using(var controller = new Duplicati.Library.Main.Controller(backup.TargetURL, options, sink))
{
((RunnerData)data).Controller = controller;
@@ -372,7 +418,7 @@ namespace Duplicati.Server
let p = SpecialFolders.ExpandEnvironmentVariables(n)
where !string.IsNullOrWhiteSpace(p)
select p).ToArray();
-
+
var r = controller.Backup(sources, filter);
UpdateMetadata(backup, r);
return r;
diff --git a/Duplicati/Server/Serializable/ImportExportStructure.cs b/Duplicati/Server/Serializable/ImportExportStructure.cs
new file mode 100644
index 000000000..f1e049a23
--- /dev/null
+++ b/Duplicati/Server/Serializable/ImportExportStructure.cs
@@ -0,0 +1,33 @@
+// Copyright (C) 2014, Kenneth Skovhede
+
+// http://www.hexad.dk, opensource@hexad.dk
+//
+// This library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 2.1 of the
+// License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+using System;
+using System.Collections.Generic;
+
+namespace Duplicati.Server.Serializable
+{
+ internal class ImportExportStructure
+ {
+ public string CreatedByVersion { get; set; }
+ public Duplicati.Server.Database.Schedule Schedule { get; set; }
+ public Duplicati.Server.Database.Backup Backup { get; set; }
+ public Dictionary<string, string> DisplayNames { get; set; }
+ }
+
+
+}
+
diff --git a/Duplicati/Server/SpecialFolders.cs b/Duplicati/Server/SpecialFolders.cs
index db40ec6df..518c3b345 100644
--- a/Duplicati/Server/SpecialFolders.cs
+++ b/Duplicati/Server/SpecialFolders.cs
@@ -109,6 +109,34 @@ namespace Duplicati.Server
Nodes = lst.ToArray();
}
+
+ internal static Dictionary<string, string> GetSourceNames(Serialization.Interface.IBackup backup)
+ {
+ var systemIO = Duplicati.Library.Snapshots.SnapshotUtility.SystemIO;
+
+ return backup.Sources.Distinct().Select(x => {
+ var sp = SpecialFolders.TranslateToDisplayString(x);
+ if (sp != null)
+ return new KeyValuePair<string, string>(x, sp);
+
+ x = SpecialFolders.ExpandEnvironmentVariables(x);
+ try {
+ var nx = x;
+ if (nx.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
+ nx = nx.Substring(0, nx.Length - 1);
+ var n = systemIO.PathGetFileName(nx);
+ if (!string.IsNullOrWhiteSpace(n))
+ return new KeyValuePair<string, string>(x, n);
+ } catch {
+ }
+
+ if (x.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()) && x.Length > 1)
+ return new KeyValuePair<string, string>(x, x.Substring(0, x.Length - 1).Substring(x.Substring(0, x.Length - 1).LastIndexOf("/") + 1));
+ else
+ return new KeyValuePair<string, string>(x, x);
+
+ }).ToDictionary(x => x.Key, x => x.Value);
+ }
}
}
diff --git a/Duplicati/Server/WebServer/ControlHandler.cs b/Duplicati/Server/WebServer/ControlHandler.cs
index 331d9bde1..4ea8e159c 100644
--- a/Duplicati/Server/WebServer/ControlHandler.cs
+++ b/Duplicati/Server/WebServer/ControlHandler.cs
@@ -665,15 +665,7 @@ namespace Duplicati.Server.WebServer
}
}
-
- private class ImportExportStructure
- {
- public string CreatedByVersion { get; set; }
- public Duplicati.Server.Database.Schedule Schedule { get; set; }
- public Duplicati.Server.Database.Backup Backup { get; set; }
- public Dictionary<string, string> DisplayNames { get; set; }
- }
-
+
private void ExportBackup(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw)
{
HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString;
@@ -692,14 +684,7 @@ namespace Duplicati.Server.WebServer
else
{
var passphrase = input["passphrase"].Value;
- var scheduleId = Program.DataConnection.GetScheduleIDsFromTags(new string[] { "ID=" + bk.ID });
-
- var ipx = new ImportExportStructure() {
- CreatedByVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(),
- Backup = (Database.Backup)bk,
- Schedule = (Database.Schedule)(scheduleId.Any() ? Program.DataConnection.GetSchedule(scheduleId.First()) : null),
- DisplayNames = GetSourceNames(bk)
- };
+ var ipx = Program.DataConnection.PrepareBackupForExport(bk);
byte[] data;
using(var ms = new System.IO.MemoryStream())
@@ -751,7 +736,7 @@ namespace Duplicati.Server.WebServer
}
else
{
- ImportExportStructure ipx;
+ Serializable.ImportExportStructure ipx;
var file = request.Form.GetFile("config");
if (file == null)
@@ -769,12 +754,12 @@ namespace Duplicati.Server.WebServer
using(var m = new Duplicati.Library.Encryption.AESEncryption(passphrase, new Dictionary<string, string>()))
using(var m2 = m.Decrypt(fs))
using(var sr = new System.IO.StreamReader(m2))
- ipx = Serializer.Deserialize<ImportExportStructure>(sr);
+ ipx = Serializer.Deserialize<Serializable.ImportExportStructure>(sr);
}
else
{
using(var sr = new System.IO.StreamReader(fs))
- ipx = Serializer.Deserialize<ImportExportStructure>(sr);
+ ipx = Serializer.Deserialize<Serializable.ImportExportStructure>(sr);
}
}
diff --git a/Duplicati/Server/WebServer/ControlMethods/GetBackup.cs b/Duplicati/Server/WebServer/ControlMethods/GetBackup.cs
index 42ef68665..d8752e153 100644
--- a/Duplicati/Server/WebServer/ControlMethods/GetBackup.cs
+++ b/Duplicati/Server/WebServer/ControlMethods/GetBackup.cs
@@ -33,7 +33,7 @@ namespace Duplicati.Server.WebServer
{
var scheduleId = Program.DataConnection.GetScheduleIDsFromTags(new string[] { "ID=" + bk.ID });
var schedule = scheduleId.Any() ? Program.DataConnection.GetSchedule(scheduleId.First()) : null;
- var sourcenames = GetSourceNames(bk);
+ var sourcenames = SpecialFolders.GetSourceNames(bk);
//TODO: Filter out the password in both settings and the target url
@@ -48,34 +48,6 @@ namespace Duplicati.Server.WebServer
});
}
}
-
- private Dictionary<string, string> GetSourceNames(Duplicati.Server.Serialization.Interface.IBackup backup)
- {
- var systemIO = Duplicati.Library.Snapshots.SnapshotUtility.SystemIO;
-
- return backup.Sources.Distinct().Select(x => {
- var sp = SpecialFolders.TranslateToDisplayString(x);
- if (sp != null)
- return new KeyValuePair<string, string>(x, sp);
-
- x = SpecialFolders.ExpandEnvironmentVariables(x);
- try {
- var nx = x;
- if (nx.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
- nx = nx.Substring(0, nx.Length - 1);
- var n = systemIO.PathGetFileName(nx);
- if (!string.IsNullOrWhiteSpace(n))
- return new KeyValuePair<string, string>(x, n);
- } catch {
- }
-
- if (x.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()) && x.Length > 1)
- return new KeyValuePair<string, string>(x, x.Substring(0, x.Length - 1).Substring(x.Substring(0, x.Length - 1).LastIndexOf("/") + 1));
- else
- return new KeyValuePair<string, string>(x, x);
-
- }).ToDictionary(x => x.Key, x => x.Value);
- }
}
}
diff --git a/Duplicati/Server/webroot/greeno/index.html b/Duplicati/Server/webroot/greeno/index.html
index f26d0b901..cd1e54f87 100644
--- a/Duplicati/Server/webroot/greeno/index.html
+++ b/Duplicati/Server/webroot/greeno/index.html
@@ -297,6 +297,18 @@
</div>
<div id="edit-tab-sourcedata">
+
+ <div class="input-wrapper">
+ <div class="edit-dialog-label" title="Choose if the backup configuration should be stored">Store configuration</div>
+ <select id="store-task-config" name="store-task-config">
+ <option value="false">Don't store setup</option>
+ <option value="true">Store this backup job setup</option>
+ <option value="all">Store all backup job setups</option>
+ </select>
+ </div>
+
+ <div class="clearfix"></div>
+
<div id="source-folder-paths" class="empty">
<div id="source-folder-droptarget"></div>
<div id="source-folder-paths-hint" class="hint-text">Click the &quot;Browse&quot; button to add folders</div>
diff --git a/Duplicati/Server/webroot/greeno/scripts/editdialog.js b/Duplicati/Server/webroot/greeno/scripts/editdialog.js
index b43e5a7b9..35aa1ca57 100644
--- a/Duplicati/Server/webroot/greeno/scripts/editdialog.js
+++ b/Duplicati/Server/webroot/greeno/scripts/editdialog.js
@@ -417,6 +417,9 @@ $(document).ready(function() {
delete dict['Backup']['Settings']['keep-versions'];
delete dict['Backup']['Settings']['keep-time'];
}
+ },
+ 'store-task-config': function(dict, key, el, cfgel) {
+ dict['Backup']['Settings']['store-task-config'] = $(el).val();
}
}
};