From c56c8d066762ebb32d241f47ef5ccd5e65efda20 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 22 Oct 2016 16:17:58 +0200 Subject: [PATCH] additional verification of hyper-v ability to show paths in GUI --- .../Library/Interface/IGenericSourceModule.cs | 13 ++- Duplicati/Library/Main/Controller.cs | 4 +- .../Library/Modules/Builtin/HyperVOptions.cs | 104 +++++++++++------- 3 files changed, 78 insertions(+), 43 deletions(-) diff --git a/Duplicati/Library/Interface/IGenericSourceModule.cs b/Duplicati/Library/Interface/IGenericSourceModule.cs index 1f1d8c0b4..aced0c6c5 100644 --- a/Duplicati/Library/Interface/IGenericSourceModule.cs +++ b/Duplicati/Library/Interface/IGenericSourceModule.cs @@ -42,13 +42,20 @@ namespace Duplicati.Library.Interface /// Filters that are applied to backup paths (include, exclude) /// A set of commandline options passed to Duplicati /// A list of changed or added options values - Dictionary ParseSource(ref string[] paths, ref string filter, Dictionary commandlineOptions); + Dictionary ParseSourcePaths(ref string[] paths, ref string filter, Dictionary commandlineOptions); /// - /// This method is the interception where the module can interact with the execution environment and modify the settings. + /// This method decides if input variables contains something to backup. /// /// A set of commandline options passed to Duplicati /// If module is going to backup anything, it returns true, otherwise false - bool ContainFiles(Dictionary commandlineOptions); + bool ContainFilesForBackup(Dictionary commandlineOptions); + + /// + /// This method decides if input variables contains something to backup. + /// + /// A set of source paths + /// If module is going to backup anything, it returns true, otherwise false + bool ContainFilesForBackup(string[] paths); } } diff --git a/Duplicati/Library/Main/Controller.cs b/Duplicati/Library/Main/Controller.cs index 3d53b0f33..3f3892dcb 100644 --- a/Duplicati/Library/Main/Controller.cs +++ b/Duplicati/Library/Main/Controller.cs @@ -181,7 +181,7 @@ namespace Duplicati.Library.Main 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); + bModulesFiles = ((Library.Interface.IGenericSourceModule)mx.Value).ContainFilesForBackup(m_options.RawOptions); if (!bModulesFiles && (inputsources == null || inputsources.Length == 0)) throw new Exception(Strings.Controller.NoSourceFoldersError); @@ -613,7 +613,7 @@ namespace Duplicati.Library.Main if (mx.Value is Library.Interface.IGenericSourceModule) { - var sourceoptions = ((Library.Interface.IGenericSourceModule)mx.Value).ParseSource(ref paths, ref pristinefilter, m_options.RawOptions); + var sourceoptions = ((Library.Interface.IGenericSourceModule)mx.Value).ParseSourcePaths(ref paths, ref pristinefilter, m_options.RawOptions); foreach (var sourceoption in sourceoptions) m_options.RawOptions[sourceoption.Key] = sourceoption.Value; diff --git a/Duplicati/Library/Modules/Builtin/HyperVOptions.cs b/Duplicati/Library/Modules/Builtin/HyperVOptions.cs index e605faf63..f8641a9bf 100644 --- a/Duplicati/Library/Modules/Builtin/HyperVOptions.cs +++ b/Duplicati/Library/Modules/Builtin/HyperVOptions.cs @@ -75,60 +75,77 @@ namespace Duplicati.Library.Modules.Builtin #endregion #region Implementation of IGenericSourceModule - public Dictionary ParseSource(ref string[] paths, ref string filter, Dictionary commandlineOptions) + public Dictionary ParseSourcePaths(ref string[] paths, ref string filter, Dictionary commandlineOptions) { - var pathshyperv = new List(); - var ret = new Dictionary(); + var changedOptions = new Dictionary(); + var filtersInclude = new List(); + var filtersExclude = new List(); - if (paths != null) - { - if (paths.Contains(m_HyperVPathAllRegExp, StringComparer.OrdinalIgnoreCase)) - { - if (Utility.Utility.IsClientWindows) - { - var hypervUtility = new HyperVUtility(); - hypervUtility.QueryHyperVGuestsInfo(); - pathshyperv = hypervUtility.Guests.Select(x => string.Format(@"%HYPERV%\{0}", x.ID)).ToList(); - } - } - else - pathshyperv = paths.Where(x => Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToList(); - } - paths = paths.Where(x => !x.Equals(m_HyperVPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray(); - if (!string.IsNullOrEmpty(filter)) { var filters = filter.Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries); - var filtersInclude = filters.Where(x => x.StartsWith("+") && Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).Select(x => x.Substring(1)).ToList(); - var filtersExclude = filters.Where(x => x.StartsWith("-") && Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).Select(x => x.Substring(1)).ToList(); + filtersInclude = filters.Where(x => x.StartsWith("+") && Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).Select(x => x.Substring(1)).ToList(); + filtersExclude = filters.Where(x => x.StartsWith("-") && Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).Select(x => x.Substring(1)).ToList(); var remainingfilters = filters.Where(x => !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase)).ToArray(); filter = string.Join(System.IO.Path.PathSeparator.ToString(), remainingfilters); - - pathshyperv = pathshyperv.Union(filtersInclude).Except(filtersExclude).ToList(); } + if (!Utility.Utility.IsClientWindows) + { + Logging.Log.WriteMessage("Hyper-V backup works only on Windows OS.", Logging.LogMessageType.Warning); + + if(paths != null) + paths = paths.Where(x => !x.Equals(m_HyperVPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray(); + } + + if (paths == null || !ContainFilesForBackup(paths) || !Utility.Utility.IsClientWindows) + return changedOptions; + + if (commandlineOptions.Keys.Contains("vss-exclude-writers")) + { + var excludedWriters = commandlineOptions["vss-exclude-writers"].Split(';').Where(x => !string.IsNullOrWhiteSpace(x) && x.Trim().Length > 0).Select(x => new Guid(x)).ToArray(); + + if (excludedWriters.Contains(HyperVUtility.HyperVWriterGuid)) + { + Logging.Log.WriteMessage(string.Format("Excluded writers for VSS cannot contain Hyper-V writer when backuping Hyper-V virtual machines. Removing \"{0}\" to continue.", HyperVUtility.HyperVWriterGuid.ToString()), Logging.LogMessageType.Warning); + + changedOptions["vss-exclude-writers"] = string.Join(";", excludedWriters.Where(x => x != HyperVUtility.HyperVWriterGuid)); + } + } + + if (!commandlineOptions.Keys.Contains("snapshot-policy") || commandlineOptions["snapshot-policy"] != "required") + { + Logging.Log.WriteMessage("Snapshot strategy have to be set to \"required\" when backuping Hyper-V virtual machines. Changing to \"required\" to continue.", Logging.LogMessageType.Warning); + changedOptions["snapshot-policy"] = "required"; + } + + var pathshyperv = new List(); + + if (paths.Contains(m_HyperVPathAllRegExp, StringComparer.OrdinalIgnoreCase)) + { + var hypervUtility = new HyperVUtility(); + hypervUtility.QueryHyperVGuestsInfo(); + pathshyperv = hypervUtility.Guests.Select(x => string.Format(@"%HYPERV%\{0}", x.ID)).ToList(); + } + else + pathshyperv = paths.Where(x => Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToList(); + + paths = paths.Where(x => !x.Equals(m_HyperVPathAllRegExp, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).ToArray(); + + if (filtersInclude.Count > 0 || filtersExclude.Count > 0) + pathshyperv = pathshyperv.Union(filtersInclude).Except(filtersExclude).ToList(); + pathshyperv = pathshyperv.Select(x => Regex.Match(x, m_HyperVGuidRegExp).Value).ToList(); - - if (pathshyperv.Count != 0 && Utility.Utility.IsClientWindows && (!commandlineOptions.Keys.Contains("snapshot-policy") || commandlineOptions["snapshot-policy"] != "required")) - { - Logging.Log.WriteMessage("Snapshot strategy have to be set to \"required\" when backuping Hyper-V virtual machines. Changing to \"required\" to continue.", Logging.LogMessageType.Information); - ret["snapshot-policy"] = "required"; - } - + if (pathshyperv.Count != 0) - { - if (Utility.Utility.IsClientWindows) - ret[OPTION_SOURCE] = string.Join(System.IO.Path.PathSeparator.ToString(), pathshyperv); - else - Logging.Log.WriteMessage("Hyper-V backup works only on Windows OS.", Logging.LogMessageType.Warning); - } + changedOptions[OPTION_SOURCE] = string.Join(System.IO.Path.PathSeparator.ToString(), pathshyperv); - return ret; + return changedOptions; } - public bool ContainFiles(Dictionary commandlineOptions) + public bool ContainFilesForBackup(Dictionary commandlineOptions) { if (commandlineOptions != null && !commandlineOptions.Keys.Contains(OPTION_SOURCE)) return false; @@ -139,6 +156,17 @@ namespace Duplicati.Library.Modules.Builtin return false; } + public bool ContainFilesForBackup(string[] paths) + { + if (paths == null) + return false; + + if (paths.Contains(m_HyperVPathAllRegExp, StringComparer.OrdinalIgnoreCase)) + return true; + + return paths.Where(x => Regex.IsMatch(x, m_HyperVPathGuidRegExp, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)).Count() > 0; + } + #endregion } }