changes in hyper-v backed
This commit is contained in:
@@ -19,54 +19,30 @@
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Duplicati.Library.Interface
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface for a plugable generic module.
|
||||
/// An interface for a plugable source module.
|
||||
/// An instance of a module is loaded prior to a backup or restore operation,
|
||||
/// and can perform tasks relating to the general execution environment, as
|
||||
/// well as modify the options used in Duplicati.
|
||||
///
|
||||
/// The implementation must have a default constructor.
|
||||
/// If the module is actually loaded, the Configure method is called.
|
||||
/// All instances where the Configure method is called will be disposed,
|
||||
/// if they implement the IDisposable interface as well.
|
||||
/// and can perform tasks relating to the source plugins, as
|
||||
/// well as modify backup source, the options and filters used in Duplicati.
|
||||
/// </summary>
|
||||
public interface IGenericSourceModule
|
||||
public interface IGenericSourceModule : IGenericModule
|
||||
{
|
||||
///// <summary>
|
||||
///// The module key, used to activate or deactivate the module on the commandline
|
||||
///// </summary>
|
||||
//string Key { get; }
|
||||
|
||||
///// <summary>
|
||||
///// A localized string describing the module with a friendly name
|
||||
///// </summary>
|
||||
//string DisplayName { get; }
|
||||
|
||||
///// <summary>
|
||||
///// A localized description of the module
|
||||
///// </summary>
|
||||
//string Description { get; }
|
||||
|
||||
///// <summary>
|
||||
///// A boolean value that indicates if the module should always be loaded.
|
||||
///// If true, the user can choose to not load the module by entering the appropriate commandline option.
|
||||
///// If false, the user can choose to load the module by entering the appropriate commandline option.
|
||||
///// </summary>
|
||||
//bool LoadAsDefault { get; }
|
||||
|
||||
///// <summary>
|
||||
///// Gets a list of supported commandline arguments
|
||||
///// </summary>
|
||||
//IList<ICommandLineArgument> SupportedCommands { get; }
|
||||
/// <summary>
|
||||
/// This method parse and alter backup source paths, apply and alter filters and returns changed or added options values.
|
||||
/// </summary>
|
||||
/// <param name="paths">Backup source paths</param>
|
||||
/// <param name="filter">Filters that are applied to backup paths (include, exclude)</param>
|
||||
/// <returns>A list of changed or added options values</returns>
|
||||
Dictionary<string, string> ParseSource(ref string[] paths, ref string filter);
|
||||
|
||||
/// <summary>
|
||||
/// This method is the interception where the module can interact with the execution environment and modify the settings.
|
||||
/// </summary>
|
||||
/// <param name="commandlineOptions">A set of commandline options passed to Duplicati</param>
|
||||
void ParseSource(ref string[] paths, ref Dictionary<string, string> commandlineOptions);
|
||||
/// <returns>If module is going to backup anything, it returns true, otherwise false</returns>
|
||||
bool ContainFiles(Dictionary<string, string> commandlineOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,10 +173,17 @@ namespace Duplicati.Library.Main
|
||||
Library.UsageReporter.Reporter.Report("USE_BACKEND", new Library.Utility.Uri(m_backend).Scheme);
|
||||
Library.UsageReporter.Reporter.Report("USE_COMPRESSION", m_options.CompressionModule);
|
||||
Library.UsageReporter.Reporter.Report("USE_ENCRYPTION", m_options.EncryptionModule);
|
||||
|
||||
|
||||
return RunAction(new BackupResults(), ref inputsources, ref filter, (result) => {
|
||||
|
||||
if (inputsources == null || inputsources.Length == 0)
|
||||
var bModulesFiles = false;
|
||||
|
||||
foreach (var mx in m_options.LoadedModules)
|
||||
if (mx.Key && mx.Value is Library.Interface.IGenericSourceModule)
|
||||
if(!bModulesFiles)
|
||||
bModulesFiles = ((Library.Interface.IGenericSourceModule)mx.Value).ContainFiles(m_options.RawOptions);
|
||||
|
||||
if (!bModulesFiles && (inputsources == null || inputsources.Length == 0))
|
||||
throw new Exception(Strings.Controller.NoSourceFoldersError);
|
||||
|
||||
var sources = new List<string>(inputsources);
|
||||
@@ -597,9 +604,8 @@ namespace Duplicati.Library.Main
|
||||
|
||||
// Make the filter read-n-write able in the generic modules
|
||||
var pristinefilter = conopts["filter"] = string.Join(System.IO.Path.PathSeparator.ToString(), FilterExpression.Serialize(filter));
|
||||
var pristinepaths = paths;
|
||||
|
||||
foreach (KeyValuePair<bool, Library.Interface.IGenericModule> mx in m_options.LoadedModules)
|
||||
foreach (var mx in m_options.LoadedModules)
|
||||
if (mx.Key)
|
||||
{
|
||||
if (mx.Value is Library.Interface.IConnectionModule)
|
||||
@@ -608,7 +614,12 @@ namespace Duplicati.Library.Main
|
||||
mx.Value.Configure(m_options.RawOptions);
|
||||
|
||||
if (mx.Value is Library.Interface.IGenericSourceModule)
|
||||
((Library.Interface.IGenericSourceModule)mx.Value).ParseSource(ref paths, ref conopts);
|
||||
{
|
||||
var sourceoptions = ((Library.Interface.IGenericSourceModule)mx.Value).ParseSource(ref paths, ref pristinefilter);
|
||||
|
||||
foreach (var sourceoption in sourceoptions)
|
||||
m_options.RawOptions[sourceoption.Key] = sourceoption.Value;
|
||||
}
|
||||
|
||||
if (mx.Value is Library.Interface.IGenericCallbackModule)
|
||||
((Library.Interface.IGenericCallbackModule)mx.Value).OnStart(result.MainOperation.ToString(), ref m_backend, ref paths);
|
||||
@@ -616,7 +627,7 @@ namespace Duplicati.Library.Main
|
||||
|
||||
// If the filters were changed, read them back in
|
||||
if (pristinefilter != conopts["filter"])
|
||||
filter = FilterExpression.Deserialize(conopts["filter"].Split(new string[] {System.IO.Path.PathSeparator.ToString()}, StringSplitOptions.RemoveEmptyEntries));
|
||||
filter = FilterExpression.Deserialize(pristinefilter.Split(new string[] {System.IO.Path.PathSeparator.ToString()}, StringSplitOptions.RemoveEmptyEntries));
|
||||
|
||||
OperationRunning(true);
|
||||
|
||||
|
||||
@@ -720,11 +720,9 @@ namespace Duplicati.Library.Main.Operation
|
||||
|
||||
m_backendLogFlushTimer = DateTime.Now.Add(FLUSH_TIMESPAN);
|
||||
System.Threading.Thread parallelScanner = null;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
using(var backend = new BackendManager(m_backendurl, m_options, m_result.BackendWriter, m_database))
|
||||
using(var filesetvolume = new FilesetVolumeWriter(m_options, m_database.OperationTimestamp))
|
||||
{
|
||||
@@ -1012,7 +1010,6 @@ namespace Duplicati.Library.Main.Operation
|
||||
|
||||
m_filehasher.Initialize();
|
||||
|
||||
|
||||
var offset = 0;
|
||||
var remaining = fs.Readblock();
|
||||
|
||||
|
||||
@@ -438,7 +438,6 @@ namespace Duplicati.Library.Main
|
||||
new CommandLineArgument("vss-exclude-writers", CommandLineArgument.ArgumentType.String, Strings.Options.VssexcludewritersShort, Strings.Options.VssexcludewritersLong),
|
||||
new CommandLineArgument("vss-use-mapping", CommandLineArgument.ArgumentType.Boolean, Strings.Options.VssusemappingShort, Strings.Options.VssusemappingLong, "false"),
|
||||
new CommandLineArgument("usn-policy", CommandLineArgument.ArgumentType.Enumeration, Strings.Options.UsnpolicyShort, Strings.Options.UsnpolicyLong, "off", null, Enum.GetNames(typeof(OptimizationStrategy))),
|
||||
new CommandLineArgument("hyperv-backup-vm", CommandLineArgument.ArgumentType.String, Strings.Options.HypervbackupvmShort, Strings.Options.HypervbackupvmLong),
|
||||
|
||||
new CommandLineArgument("encryption-module", CommandLineArgument.ArgumentType.String, Strings.Options.EncryptionmoduleShort, Strings.Options.EncryptionmoduleLong, "aes"),
|
||||
new CommandLineArgument("compression-module", CommandLineArgument.ArgumentType.String, Strings.Options.CompressionmoduleShort, Strings.Options.CompressionmoduleLong, "zip"),
|
||||
|
||||
@@ -19,14 +19,13 @@
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Duplicati.Library.Snapshots;
|
||||
|
||||
namespace Duplicati.Library.Modules.Builtin
|
||||
{
|
||||
public class HyperVOptions : Interface.IGenericModule, Interface.IGenericSourceModule
|
||||
public class HyperVOptions : Interface.IGenericSourceModule
|
||||
{
|
||||
private const string OPTION_SOURCE = "hyperv-backup-vm";
|
||||
|
||||
@@ -39,12 +38,12 @@ namespace Duplicati.Library.Modules.Builtin
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get { return Strings.HttpOptions.DisplayName; }
|
||||
get { return Strings.HyperVOptions.DisplayName; }
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get { return Strings.HttpOptions.Description; }
|
||||
get { return Strings.HyperVOptions.Description; }
|
||||
}
|
||||
|
||||
public bool LoadAsDefault
|
||||
@@ -52,9 +51,9 @@ namespace Duplicati.Library.Modules.Builtin
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public IList<Duplicati.Library.Interface.ICommandLineArgument> SupportedCommands
|
||||
public IList<Interface.ICommandLineArgument> SupportedCommands
|
||||
{
|
||||
get { return new List<Duplicati.Library.Interface.ICommandLineArgument>(); }
|
||||
get { return new List<Interface.ICommandLineArgument>(); }
|
||||
}
|
||||
|
||||
public void Configure(IDictionary<string, string> commandlineOptions)
|
||||
@@ -64,12 +63,13 @@ namespace Duplicati.Library.Modules.Builtin
|
||||
#endregion
|
||||
|
||||
#region Implementation of IGenericSourceModule
|
||||
public void ParseSource(ref string[] paths, ref Dictionary<string, string> commandlineOptions)
|
||||
public Dictionary<string, string> ParseSource(ref string[] paths, ref string filter)
|
||||
{
|
||||
var hypervpathguidexp = @"%HYPERV:(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}%";
|
||||
var hypervguidexp = @"(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}";
|
||||
var hypervpathallexp = @"%HYPERV:*%";
|
||||
var pathshyperv = new List<string>();
|
||||
var ret = new Dictionary<string, string>();
|
||||
|
||||
if (paths.Contains(hypervpathallexp, StringComparer.OrdinalIgnoreCase))
|
||||
pathshyperv = new HyperVUtility().GetHyperVGuests().Select(x => string.Format("%HYPERV:{0}%", x.ID)).ToList();
|
||||
@@ -78,20 +78,33 @@ namespace Duplicati.Library.Modules.Builtin
|
||||
|
||||
paths = paths.Where(x => !x.Equals(hypervpathallexp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, hypervpathguidexp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray();
|
||||
|
||||
if (commandlineOptions.Keys.Contains("filter"))
|
||||
if (!string.IsNullOrEmpty(filter))
|
||||
{
|
||||
var filters = commandlineOptions["filter"].Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var filters = filter.Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var filtersInclude = filters.Where(x => x.StartsWith("+") && Regex.IsMatch(x, hypervpathguidexp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).Select(x => x.Substring(1)).ToList();
|
||||
var filtersExclude = filters.Where(x => x.StartsWith("-") && Regex.IsMatch(x, hypervpathguidexp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).Select(x => x.Substring(1)).ToList();
|
||||
|
||||
var remainingfilters = filters.Where(x => !Regex.IsMatch(x, hypervpathguidexp, RegexOptions.IgnoreCase)).ToArray();
|
||||
commandlineOptions["filter"] = string.Join(System.IO.Path.PathSeparator.ToString(), remainingfilters);
|
||||
filter = string.Join(System.IO.Path.PathSeparator.ToString(), remainingfilters);
|
||||
|
||||
pathshyperv = pathshyperv.Union(filtersInclude).Except(filtersExclude).ToList();
|
||||
}
|
||||
|
||||
pathshyperv = pathshyperv.Select(x => Regex.Match(x, hypervguidexp).Value).ToList();
|
||||
commandlineOptions[OPTION_SOURCE] = string.Join(System.IO.Path.PathSeparator.ToString(), pathshyperv);
|
||||
ret[OPTION_SOURCE] = string.Join(System.IO.Path.PathSeparator.ToString(), pathshyperv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool ContainFiles(Dictionary<string, string> commandlineOptions)
|
||||
{
|
||||
if (commandlineOptions != null && !commandlineOptions.Keys.Contains(OPTION_SOURCE))
|
||||
return false;
|
||||
|
||||
if (commandlineOptions[OPTION_SOURCE].Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries).Count() > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -31,7 +31,11 @@ namespace Duplicati.Library.Modules.Builtin.Strings {
|
||||
public static string OauthurlLong { get { return LC.L(@"Duplicati uses an external server to support the OAuth authentication flow. If you have set up your own Duplicati OAuth server, you can supply the refresh url."); } }
|
||||
public static string SslversionsShort { get { return LC.L(@"Sets allowed SSL versions"); } }
|
||||
public static string SslversionsLong { get { return LC.L(@"This option changes the default SSL versions allowed. This is an advanced option and should only be used if you want to enhance security or work around an issue with a particular SSL protocol."); } }
|
||||
}
|
||||
}
|
||||
internal static class HyperVOptions {
|
||||
public static string Description { get { return LC.L(@"This module works internaly to parse source parameters to backup Hyper-V virtual machines"); } }
|
||||
public static string DisplayName { get { return LC.L(@"Configure Hyper-V module"); } }
|
||||
}
|
||||
internal static class RunScript {
|
||||
public static string Description { get { return LC.L(@"Executes a script before starting an operation, and again on completion"); } }
|
||||
public static string DisplayName { get { return LC.L(@"Run script"); } }
|
||||
|
||||
Reference in New Issue
Block a user