private void BackupFiles(IList<IVssWMComponent> components, IDictionary<string, string> volumeMap, IDictionary<string, string> snapshotVolumeMap, IDictionary<string, string> vmNamesMap, Options options) { IList<System.IO.Stream> streams = new List<System.IO.Stream>(); try { foreach (var component in components) { string vmBackupPath = Path.Combine(options.Output, string.Format(options.OutputFormat, vmNamesMap[component.ComponentName], component.ComponentName, DateTime.Now, "7z")); File.Delete(vmBackupPath); var files = new Dictionary<string, System.IO.Stream>(); foreach (var file in component.Files) { string path; if (file.IsRecursive) path = file.Path; else path = Path.Combine(file.Path, file.FileSpecification); // Get the longest matching path var volumePath = volumeMap.Keys.OrderBy((o) => o.Length).Reverse().Where((o) => path.StartsWith(o, StringComparison.OrdinalIgnoreCase)).First(); var volumeName = volumeMap[volumePath]; var fileName = Path.GetFileName(path.Substring(volumePath.Length)).ToUpperInvariant(); var include = Path.GetExtension(fileName).ToLowerInvariant() != ".avhdx" && Path.GetExtension(fileName).ToLowerInvariant() != ".vmrs"; if (include && options.VhdInclude != null) { if (options.VhdInclude.Count(x => string.CompareOrdinal(x.ToUpperInvariant(), fileName) == 0) == 0) include = false; } if (include && options.VhdIgnore != null) { if (options.VhdIgnore.Count(x => string.CompareOrdinal(x.ToUpperInvariant(), fileName) == 0) != 0) include = false; } if (include) AddPathToSevenZip(files, streams, snapshotVolumeMap[volumeName], volumePath.Length, path); } SevenZipExtractor.SetLibraryPath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "7z.dll")); var sevenZip = new SevenZipCompressor(); sevenZip.ArchiveFormat = OutArchiveFormat.SevenZip; sevenZip.CompressionMode = CompressionMode.Create; sevenZip.DirectoryStructure = true; sevenZip.PreserveDirectoryRoot = false; sevenZip.CustomParameters.Add("mt", "on"); switch (options.CompressionLevel) { case 0: sevenZip.CompressionLevel = CompressionLevel.None; break; case 1: sevenZip.CompressionLevel = CompressionLevel.Fast; break; case 2: sevenZip.CompressionLevel = CompressionLevel.Fast; break; case 3: sevenZip.CompressionLevel = CompressionLevel.Low; break; case 4: sevenZip.CompressionLevel = CompressionLevel.Low; break; case 5: sevenZip.CompressionLevel = CompressionLevel.Low; break; case 6: sevenZip.CompressionLevel = CompressionLevel.Normal; break; case 7: sevenZip.CompressionLevel = CompressionLevel.High; break; case 8: sevenZip.CompressionLevel = CompressionLevel.High; break; case 9: sevenZip.CompressionLevel = CompressionLevel.Ultra; break; } if (BackupProgress != null) { sevenZip.FileCompressionStarted += (sender, e) => { var ebp = new BackupProgressEventArgs() { AcrhiveFileName = e.FileName, Action = EventAction.StartingArchive }; sevenZipCurrentFile = e.FileName; Report7ZipProgress(component, volumeMap, ebp); if (cancel) { e.Cancel = true; } }; sevenZip.FileCompressionFinished += (sender, e) => { var ebp = new BackupProgressEventArgs() { AcrhiveFileName = sevenZipCurrentFile, Action = EventAction.ArchiveDone }; sevenZipCurrentFile = String.Empty; Report7ZipProgress(component, volumeMap, ebp); }; sevenZip.Compressing += (sender, e) => { var ebp = new BackupProgressEventArgs() { AcrhiveFileName = sevenZipCurrentFile, Action = EventAction.PercentProgress, CurrentEntry = sevenZipCurrentFile, PercentDone = e.PercentDone }; Report7ZipProgress(component, volumeMap, ebp); if (cancel) { e.Cancel = true; } }; } if (string.IsNullOrEmpty(options.Password)) sevenZip.CompressStreamDictionary(files, vmBackupPath); else sevenZip.CompressStreamDictionary(files, vmBackupPath, options.Password); if (cancel) { if (File.Exists(vmBackupPath)) { File.Delete(vmBackupPath); } throw new BackupCancelledException(); } } } finally { // Make sure that all streams are closed foreach (var s in streams) s.Close(); } }
private void BackupSubset(IDictionary<string, string> vmNamesMapSubset, Options options) { IVssImplementation vssImpl = VssUtils.LoadImplementation(); using (IVssBackupComponents vss = vssImpl.CreateVssBackupComponents()) { RaiseEvent(EventAction.InitializingVSS, null, null); vss.InitializeForBackup(null); vss.SetBackupState(true, true, VssBackupType.Full, false); vss.SetContext(VssSnapshotContext.Backup); // Add Hyper-V writer Guid hyperVwriterGuid = new Guid("66841cd4-6ded-4f4b-8f17-fd23f8ddc3de"); vss.EnableWriterClasses(new Guid[] { hyperVwriterGuid }); vss.GatherWriterMetadata(); IList<IVssWMComponent> components = new List<IVssWMComponent>(); // key: volumePath, value: volumeName. These values are equivalent on a standard volume, but differ in the CSV case IDictionary<string, string> volumeMap = new Dictionary<string, string>(); var wm = vss.WriterMetadata.Where((o) => o.WriterId.Equals(hyperVwriterGuid)).FirstOrDefault(); foreach (var component in wm.Components) { if (vmNamesMapSubset.ContainsKey(component.ComponentName)) { components.Add(component); vss.AddComponent(wm.InstanceId, wm.WriterId, component.Type, component.LogicalPath, component.ComponentName); foreach (var file in component.Files) { string volumeName = null; string volumePath = null; volumePath = Path.GetPathRoot(file.Path).ToUpper(); volumeName = volumePath; if (!volumeMap.ContainsKey(volumePath)) volumeMap.Add(volumePath, volumeName); } } } if (components.Count > 0) { Guid vssSet = vss.StartSnapshotSet(); // Key: volumeName, value: snapshotGuid IDictionary<string, Guid> snapshots = new Dictionary<string, Guid>(); foreach (var volumeName in volumeMap.Values) snapshots.Add(volumeName, vss.AddToSnapshotSet(volumeName, Guid.Empty)); vss.PrepareForBackup(); RaiseEvent(EventAction.StartingSnaphotSet, components, volumeMap); vss.DoSnapshotSet(); RaiseEvent(EventAction.SnapshotSetDone, components, volumeMap); // key: volumeName, value: snapshotVolumePath IDictionary<string, string> snapshotVolumeMap = new Dictionary<string, string>(); foreach (var kv in snapshots) snapshotVolumeMap.Add(kv.Key, vss.GetSnapshotProperties(kv.Value).SnapshotDeviceObject); BackupFiles(components, volumeMap, snapshotVolumeMap, vmNamesMapSubset, options); foreach (var component in components) vss.SetBackupSucceeded(wm.InstanceId, wm.WriterId, component.Type, component.LogicalPath, component.ComponentName, true); vss.BackupComplete(); RaiseEvent(EventAction.DeletingSnapshotSet, components, volumeMap); vss.DeleteSnapshotSet(vssSet, true); } } }
public IDictionary<string, string> VSSBackup(IEnumerable<string> vmNames, VMNameType nameType, Options options) { cancel = false; var vmNamesMap = GetVMNames(vmNames, nameType); if (vmNamesMap.Count > 0) { if (options.SingleSnapshot) BackupSubset(vmNamesMap, options); else foreach (var kv in vmNamesMap) { var vmNamesMapSubset = new Dictionary<string, string>(); vmNamesMapSubset.Add(kv.Key, kv.Value); BackupSubset(vmNamesMapSubset, options); } } return vmNamesMap; }
private static void Main(string[] args) { _logger = LogManager.GetCurrentClassLogger(); var options = new Options(); try { var stopwatch = new Stopwatch(); stopwatch.Start(); System.Console.WriteLine("HyperVBackup 3"); System.Console.WriteLine("Copyright (C) 2012 Cloudbase Solutions SRL"); System.Console.WriteLine("Copyright (C) 2016/2017 Coliseo Software SRL"); _logger.Info($"HyperVBackup started at {DateTime.Now}"); if (!IsAdministrator()) { throw new Exception("HyperVBackup requires administrator permissions"); } var parser = new Parser(ConfigureSettings); if (parser.ParseArgumentsStrict(args, options, () => Environment.Exit(1))) { GetConsoleWidth(); System.Console.WriteLine(); var vmNames = GetVmNames(options); if (vmNames == null) { _logger.Info("Backing up all VMs on this server"); } if (!Directory.Exists(options.Output)) { throw new Exception($"The folder \"{options.Output}\" is not valid"); } if (options.CleanOutputDays != 0) { CleanOutputByDays(options.Output, options.CleanOutputDays); } if (options.CleanOutputMb != 0) { CleanOutputByMegabytes(options.Output, options.CleanOutputMb); } var nameType = options.Name ? VmNameType.ElementName : VmNameType.SystemName; var mgr = new BackupManager(); mgr.BackupProgress += MgrBackupProgress; System.Console.CancelKeyPress += Console_CancelKeyPress; var backupOptions = new HyperVBackUp.Engine.Options { CompressionLevel = options.CompressionLevel, Output = options.Output, OutputFormat = options.OutputFormat, SingleSnapshot = options.SingleSnapshot, VhdInclude = options.VhdInclude, VhdIgnore = options.VhdIgnore, Password = options.Password, ZipFormat = options.ZipFormat, DirectCopy = options.DirectCopy, MultiThreaded = options.MultiThreaded, Exclude = options.Exclude }; var vmNamesMap = mgr.VssBackup(vmNames, nameType, backupOptions, _logger); var success = CheckRequiredVMs(vmNames, nameType, vmNamesMap); ShowElapsedTime(stopwatch); if (success) { if (!string.IsNullOrEmpty(options.OnSuccess)) { _logger.Info("Executing OnSucess program"); ExecuteProcess(options.OnSuccess, _logger); } } else { if (!string.IsNullOrEmpty(options.OnFailure)) { _logger.Info("Executing OnFailure program"); ExecuteProcess(options.OnFailure, _logger); } } _logger.Info($"HyperVBackup ended at {DateTime.Now}"); } } catch (BackupCancelledException ex) { System.Console.Error.WriteLine(string.Format(ex.Message)); _logger.Error(ex.ToString()); if (!string.IsNullOrEmpty(options.OnFailure)) { _logger.Info("Executing OnFailure program"); ExecuteProcess(options.OnFailure, _logger); } Environment.Exit(3); } catch (Exception ex) { System.Console.Error.WriteLine($"Error: {ex.Message}"); System.Console.Error.WriteLine(ex.StackTrace); _logger.Error(ex.ToString()); if (!string.IsNullOrEmpty(options.OnFailure)) { _logger.Info("Executing OnFailure program"); ExecuteProcess(options.OnFailure, _logger); } Environment.Exit(2); } Environment.Exit(_cancel ? 3 : 0); }
private static IEnumerable<string> GetVMNames(Options options) { IEnumerable<string> vmNames = null; if (options.File != null) vmNames = File.ReadAllLines(options.File); else if (options.List != null) vmNames = options.List; if (vmNames != null) vmNames = (from o in vmNames where o.Trim().Length > 0 select o.Trim()); return vmNames; }
static void Main(string[] args) { try { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); System.Console.WriteLine("HyperVBackup 2.0"); System.Console.WriteLine("Copyright (C) 2012 Cloudbase Solutions Srl"); System.Console.WriteLine("Copyright (C) 2015 Coliseo Software Srl"); var parser = new Parser(ConfigureSettings); var options = new Options(); if (parser.ParseArgumentsStrict(args, options, () => Environment.Exit(1))) { GetConsoleWidth(); var vmNames = GetVMNames(options); System.Console.WriteLine(); if (vmNames == null) System.Console.WriteLine("Backing up all VMs on this server"); if (!Directory.Exists(options.Output)) throw new Exception(string.Format("The folder \"{0}\" is not valid", options.Output)); VMNameType nameType = options.Name ? VMNameType.ElementName : VMNameType.SystemName; BackupManager mgr = new BackupManager(); mgr.BackupProgress += MgrBackupProgress; System.Console.CancelKeyPress += Console_CancelKeyPress; var backupOptions = new HyperVBackUp.Engine.Options { CompressionLevel = options.CompressionLevel, Output = options.Output, OutputFormat = options.OutputFormat, SingleSnapshot = options.SingleSnapshot, VhdInclude = options.VhdInclude, VhdIgnore = options.VhdIgnore, Password = options.Password }; var vmNamesMap = mgr.VSSBackup(vmNames, nameType, backupOptions); CheckRequiredVMs(vmNames, nameType, vmNamesMap); ShowElapsedTime(stopwatch); } } catch (BackupCancelledException ex) { System.Console.Error.WriteLine(string.Format(ex.Message)); Environment.Exit(3); } catch (Exception ex) { System.Console.Error.WriteLine(string.Format("Error: {0}", ex.Message)); System.Console.Error.WriteLine(ex.StackTrace); Environment.Exit(2); } Environment.Exit(cancel ? 3 : 0); }
static void Main(string[] args) { try { var stopwatch = new Stopwatch(); stopwatch.Start(); System.Console.WriteLine("HyperVBackup 2.2"); System.Console.WriteLine("Copyright (C) 2012 Cloudbase Solutions Srl"); System.Console.WriteLine("Copyright (C) 2016 Coliseo Software Srl"); var parser = new Parser(ConfigureSettings); var options = new Options(); if (parser.ParseArgumentsStrict(args, options, () => Environment.Exit(1))) { GetConsoleWidth(); System.Console.WriteLine(); if (options.CleanOutputDays != 0) { CleanOutputByDays(options.Output, options.CleanOutputDays); } if (options.CleanOutputMb != 0) { CleanOutputByMegabytes(options.Output, options.CleanOutputMb); } var vmNames = GetVmNames(options); if (vmNames == null) { System.Console.WriteLine("Backing up all VMs on this server"); } if (!Directory.Exists(options.Output)) { throw new Exception($"The folder \"{options.Output}\" is not valid"); } if (options.CleanOutputDays != 0) { CleanOutputByDays(options.Output, options.CleanOutputDays); } if (options.CleanOutputMb != 0) { CleanOutputByMegabytes(options.Output, options.CleanOutputMb); } var nameType = options.Name ? VmNameType.ElementName : VmNameType.SystemName; var mgr = new BackupManager(); mgr.BackupProgress += MgrBackupProgress; System.Console.CancelKeyPress += Console_CancelKeyPress; var backupOptions = new HyperVBackUp.Engine.Options { CompressionLevel = options.CompressionLevel, Output = options.Output, OutputFormat = options.OutputFormat, SingleSnapshot = options.SingleSnapshot, VhdInclude = options.VhdInclude, VhdIgnore = options.VhdIgnore, Password = options.Password, ZipFormat = options.ZipFormat, DirectCopy = options.DirectCopy }; var vmNamesMap = mgr.VssBackup(vmNames, nameType, backupOptions); CheckRequiredVMs(vmNames, nameType, vmNamesMap); ShowElapsedTime(stopwatch); } } catch (BackupCancelledException ex) { System.Console.Error.WriteLine(string.Format(ex.Message)); Environment.Exit(3); } catch (Exception ex) { System.Console.Error.WriteLine($"Error: {ex.Message}"); System.Console.Error.WriteLine(ex.StackTrace); Environment.Exit(2); } Environment.Exit(_cancel ? 3 : 0); }