public Snapshot Create(SnapshotSupportedLevel level) { return(new Snapshot()); }
public ISnapshot[] CreateVolumeSnapShot(List <FileSystem> volumes, string[] specialObjects, SnapshotSupportedLevel level) { ArrayList snapshots = new ArrayList(); foreach (FileSystem volume in volumes) { Snapshot sn = new Snapshot(); sn.Type = this.Name; //volumeName = volumeName.Substring(1); Logger.Append(Severity.DEBUG, "1/2 Snapshotting Btrfs volume " + volume.MountPoint); string snapshotName = "backup_" + DateTime.Now.ToString("yyyyMMdd-hh:mm"); ProcessStartInfo pi = new ProcessStartInfo("btrfs", "subvolume snapshot " + volume.MountPoint + " " + volume.MountPoint + "/" + volume.MountPoint.Substring(0, volume.MountPoint.LastIndexOf('/')) + "@" + snapshotName); pi.RedirectStandardOutput = true; pi.RedirectStandardError = true; pi.UseShellExecute = false; sn.TimeStamp = Utilities.Utils.GetUtcUnixTime(DateTime.UtcNow); using (Process p = Process.Start(pi)){ p.WaitForExit(); string stdOut = p.StandardOutput.ReadToEnd(); string stdErr = p.StandardError.ReadToEnd(); if (stdErr != String.Empty) // something went wrong, on success the command returns nothing { throw new Exception("Unable to snapshot Btrfs volume '" + volume.MountPoint + "'. Error : '" + stdErr + "' (std output was: '" + stdOut + "')"); } else { Logger.Append(Severity.DEBUG, "2/2 Successfully snapshotted " + volume.MountPoint + " to " + snapshotName); } } sn.Path = volume.MountPoint; sn.Id = Guid.Empty; //sn.Path = volume.MountPoint+"/"+volume.MountPoint.Substring(0, volume.MountPoint.LastIndexOf('/'))+"@"+snapshotName; //sn.MountPoint = System.IO.Path.Combine(volume.MountPoint, "@"+snapshotName); sn.MountPoint = volume.MountPoint + "/" + "@" + snapshotName; snapshots.Add(sn); } return((ISnapshot[])snapshots.ToArray(typeof(ISnapshot))); }
public ISnapshot[] CreateVolumeSnapShot(List <FileSystem> volumes, string[] specialObjects, SnapshotSupportedLevel level) { ArrayList snapshots = new ArrayList(); // We need the lvm block device path, so let's use VolumeManager FileSystem[] lvmVolumes = FilesystemManager.GetLVMDrives(); foreach (FileSystem volume in volumes) { /*string blockDevice = String.Empty; * foreach(SpecialDrive sd in lvmVolumes){ * if(volumeName == sd.MountPoint) * blockDevice = sd.BlockDevice; * }*/ Snapshot sn = new Snapshot(); sn.Type = this.Name; Logger.Append(Severity.DEBUG, "1/3 Snapshotting volume " + volume.MountPoint + " (" + volume.Path + ")"); string snapshotName = volume.MountPoint.Substring(1) + "__backup_DONOTREMOVE_" + DateTime.Now.ToString("yyyyMMdd-hh-mm-ss"); string lvmParams = "lvcreate --size 1G --permission r --snapshot --name " + snapshotName + " " + volume.Path; ProcessStartInfo pi = new ProcessStartInfo("lvm", lvmParams); pi.RedirectStandardOutput = true; pi.RedirectStandardError = true; pi.UseShellExecute = false; sn.TimeStamp = Utilities.Utils.GetUtcUnixTime(DateTime.UtcNow); Process p = Process.Start(pi); p.WaitForExit(); // we don't check stdout nor stderr, due to how crappy is lvm can be in its output //(reports errors due to bad scanning which didn't prevent cnapshot from being created) //string stdOut = p.StandardOutput.ReadToEnd(); string stdErr = p.StandardError.ReadToEnd(); /*if(stdErr.Length >5) // something went wrong * throw new Exception("Unable to snapshot LVM volume '"+volumeName+"'. Error : '"+stdErr.Replace(Environment.NewLine, " - ") +"' (std output was: '"+stdOut.Replace(Environment.NewLine, " - ")+"'). command was : 'lvm "+lvmParams+"'"); * else*/ Logger.Append(Severity.DEBUG, "2/3 Successfully snapshotted " + volume.MountPoint + " to " + snapshotName); string mountPoint = ConfigManager.GetValue("Backups.TempFolder") + "/" + snapshotName + "/"; Directory.CreateDirectory(mountPoint); // now mount it, the good old way string mountCommand = volume.Path.Substring(0, volume.Path.LastIndexOf("/") + 1) + snapshotName + " " + mountPoint; ProcessStartInfo mountInfo = new ProcessStartInfo("mount", mountCommand); mountInfo.RedirectStandardOutput = true; mountInfo.RedirectStandardError = true; mountInfo.UseShellExecute = false; Process mount = Process.Start(mountInfo); mount.WaitForExit(); string mountOut = mount.StandardOutput.ReadToEnd(); string mountErr = mount.StandardError.ReadToEnd(); //if(mountErr != String.Empty) // something went wrong, on success the command returns nothing // throw new Exception("Unable to mount snapshot for '"+volumeName+"'. Error : '"+mountErr+"' (std output was: '"+mountOut+"', command was 'mount "+mountCommand+"')"); //else FileSystem[] lvmWithSnap = FilesystemManager.GetLVMDrives(); bool found = false; foreach (FileSystem theVol in lvmWithSnap) { if (snapshotName == theVol.MountPoint) { Logger.Append(Severity.DEBUG, "3/3 Successfully mounted " + snapshotName + " to " + mountPoint); found = true; } } if (found == false) { throw new Exception("Unable to snapshot or mount for '" + volume.MountPoint + "'. mount Error : '" + mountErr + "', snapshot Error :" + stdErr); } sn.Path = volume.MountPoint; sn.Id = Guid.Empty; sn.MountPoint = mountPoint; snapshots.Add(sn); } return((ISnapshot[])snapshots.ToArray(typeof(ISnapshot))); }
public ISnapshot[] CreateVolumeSnapShot(List <FileSystem> volumes, string[] spoPaths, SnapshotSupportedLevel level) { using (new Alphaleonis.Win32.Security.PrivilegeEnabler(Privilege.Backup, Privilege.Restore)){ //PrivilegesManager pm = new PrivilegesManager(); //pm.Grant(); VssBackupType vssLevel = VssBackupType.Full; if (level == SnapshotSupportedLevel.Full) { vssLevel = VssBackupType.Full; } else if (level == SnapshotSupportedLevel.Incremental) { vssLevel = VssBackupType.Incremental; } else if (level == SnapshotSupportedLevel.Differential) { vssLevel = VssBackupType.Differential; } else if (level == SnapshotSupportedLevel.TransactionLog) { vssLevel = VssBackupType.Log; } ArrayList snapshots = new ArrayList(); Metadata = new SPOMetadata(); bool snapshotSuccedeed = false; try{ IVssImplementation vss = VssUtils.LoadImplementation(); backup = vss.CreateVssBackupComponents(); Logger.Append(Severity.DEBUG, "0/6 Initializing Snapshot (" + ((spoPaths == null)? "NON-component mode" : "component mode") + ", level " + level + ")"); backup.InitializeForBackup(null); if (spoPaths == null) // component-less snapshot set { backup.SetBackupState(false, true, VssBackupType.Full, false); } else { backup.SetBackupState(true, true, vssLevel, (vssLevel == VssBackupType.Full)?false:true); } if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { // The only context supported on Windows XP is VssSnapshotContext.Backup backup.SetContext(VssSnapshotContext.AppRollback /*|VssSnapshotContext.All*/); } Logger.Append(Severity.DEBUG, "1/6 Gathering writers metadata and status"); using (IVssAsync async = backup.GatherWriterMetadata()){ async.Wait(); async.Dispose(); } // gather writers status before adding backup set components using (IVssAsync async = backup.GatherWriterStatus()){ async.Wait(); async.Dispose(); } Logger.Append(Severity.DEBUG, "2/6 Adding writers and components"); // Now we add the components (vss writers, writer paths/params) of this snapshot set if (spoPaths != null) { foreach (IVssExamineWriterMetadata writer in backup.WriterMetadata) { foreach (string spo in spoPaths) { //Logger.Append (Severity.TRIVIA, "Searching writer and/or component matching "+spo); int index = spo.IndexOf(writer.WriterName); if (index < 0 && spo != "*") { continue; } bool found = false; Logger.Append(Severity.TRIVIA, "Found matching writer " + writer.WriterName + ", instance name=" + writer.InstanceName); // First we check that the writer's status is OK, else we don't add it to avoid failure of complete snapshot if it's not bool writerOk = false; foreach (VssWriterStatusInfo status in backup.WriterStatus) { if (status.Name == writer.WriterName) { Logger.Append(Severity.TRIVIA, "Checking required writer " + status.Name + ", status=" + status.State.ToString() + ", error state=" + status.Failure.ToString()); if (status.State == VssWriterState.Stable && status.Failure == VssError.Success) // if we get there it means that we are ready to add the wanted component to VSS set { writerOk = true; } else { Logger.Append(Severity.ERROR, "Cannot add writer " + status.Name + " to snapshot set," + " status=" + status.State.ToString() + ". Backup data managed by this writer may not be consistent"); if (LogEvent != null) { LogEvent(this, new LogEventArgs(820, Severity.WARNING, status.Name + ", Status=" + status.State.ToString() + ", Failure=" + status.Failure.ToString())); } } } } if (!writerOk) { if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { backup.DisableWriterClasses(new Guid[] { writer.WriterId }); } continue; } bool addAllComponents = false; if (spo.Length == index + writer.WriterName.Length || spo == "*" || spo == "" + writer.WriterName + @"\*") { addAllComponents = true; } foreach (IVssWMComponent component in writer.Components) { found = false; //Console.WriteLine("createvolsnapshot : current component is :"+component.LogicalPath+@"\"+component.ComponentName); if ((!addAllComponents) && spo.IndexOf(component.LogicalPath + @"\" + component.ComponentName) < 0) { continue; } //Logger.Append (Severity.TRIVIA, "Asked to recursively select all '"+writer.WriterName+"' writer's components"); if (OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) { foreach (VssWMDependency dep in component.Dependencies) { Logger.Append(Severity.TRIVIA, "Component " + component.ComponentName + " depends on component " + dep.ComponentName); } } if (component.Selectable) { backup.AddComponent(writer.InstanceId, writer.WriterId, component.Type, component.LogicalPath, component.ComponentName); } Logger.Append(Severity.INFO, "Added writer '" + writer.WriterName + "' component " + component.ComponentName); found = true; // Second we need to find every drive containing files necessary for writer's backup // and add them to drives list, in case they weren't explicitely selected as part of backuppaths List <VssWMFileDescription> componentFiles = new List <VssWMFileDescription>(); componentFiles.AddRange(component.Files); componentFiles.AddRange(component.DatabaseFiles); componentFiles.AddRange(component.DatabaseLogFiles); foreach (VssWMFileDescription file in componentFiles) { if (string.IsNullOrEmpty(file.Path)) { continue; } //Console.WriteLine ("component file path="+file.Path+", alt backuplocation="+file.AlternateLocation // +", backuptypemask="+file.BackupTypeMask.ToString()+", spec="+file.FileSpecification+", recursive="+file.IsRecursive); // TODO : Reuse GetInvolvedDrives (put it into VolumeManager class) string drive = file.Path.Substring(0, 3).ToUpper(); if (drive.Contains(":") && drive.Contains("\\")) { var searchedVol = from FileSystem vol in volumes where vol.MountPoint.Contains(drive) select vol; //if(!volumes.Contains(drive)){ if (searchedVol == null) { Logger.Append(Severity.INFO, "Select VSS component " + component.LogicalPath + @"\" + component.ComponentName + " requires snapshotting of drive " + drive + ", adding it to the list."); volumes.Add(searchedVol.First()); } break; } } //Logger.Append(Severity.TRIVIA, "Added writer/component "+spo); //break; } //metadata.Metadata.Add(writer.SaveAsXml()); Metadata.Metadata.Add(writer.WriterName, writer.SaveAsXml()); if (found == false) { Logger.Append(Severity.WARNING, "Could not find VSS component " + spo + " which was part of backup paths"); } } } } Logger.Append(Severity.DEBUG, "3/6 Preparing Snapshot "); //backup.SetBackupState(false, true, VssBackupType.Full, false); Guid snapID = backup.StartSnapshotSet(); //Guid volID = new Guid(); foreach (FileSystem volume in volumes) { VSSSnapshot snapshot = new VSSSnapshot(); snapshot.Type = this.Name; Logger.Append(Severity.DEBUG, "Preparing Snapshot of " + volume.MountPoint); if (volume.MountPoint != null && backup.IsVolumeSupported(volume.MountPoint)) { snapshot.Id = backup.AddToSnapshotSet(volume.MountPoint); snapshot.Path = volume.MountPoint; } else // return the fake provider to get at least a degraded backup, better than nothing { Logger.Append(Severity.WARNING, "Volume '" + volume.MountPoint + "' is not snapshottable (or null). Backup will be done without snapshot, risks of data inconsistancy."); ISnapshotProvider fakeSnapProvider = SnapshotProvider.GetProvider("NONE"); List <FileSystem> fakeList = new List <FileSystem>(); fakeList.Add(volume); snapshot = (VSSSnapshot)fakeSnapProvider.CreateVolumeSnapShot(fakeList, null, SnapshotSupportedLevel.Full)[0]; } if (snapshot.Id == System.Guid.Empty) { Logger.Append(Severity.ERROR, "Unable to add drive " + volume.MountPoint + " to snapshot set (null guid)"); } else { Logger.Append(Severity.TRIVIA, "Drive " + volume.MountPoint + " will be snapshotted to " + snapshot.Id); } snapshots.Add(snapshot); } Logger.Append(Severity.DEBUG, "4/6 Calling Prepare..."); using (IVssAsync async = backup.PrepareForBackup()){ async.Wait(); async.Dispose(); } Logger.Append(Severity.DEBUG, "5/6 Snapshotting volumes"); using (IVssAsync async = backup.DoSnapshotSet()){ async.Wait(); async.Dispose(); } //if(OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)) foreach (IVssExamineWriterMetadata w in backup.WriterMetadata) { foreach (IVssWMComponent comp in w.Components) { try{ backup.SetBackupSucceeded(w.InstanceId, w.WriterId, comp.Type, comp.LogicalPath, comp.ComponentName, true); Logger.Append(Severity.TRIVIA, "Component " + comp.ComponentName + " has been notified about backup success."); } catch (Exception) { //Logger.Append (Severity.WARNING, "Could not notify component "+comp.ComponentName+" about backup completion : "+se.Message); } } } //Node.Misc.VSSObjectHandle.StoreObject(backup); try{ //on XP backupcomplete consider that we have done with the snapshot and releases it. //if(OperatingSystemInfo.IsAtLeast(OSVersionName.WindowsServer2003)){ backup.BackupComplete(); Metadata.Metadata.Add("_bcd_", backup.SaveAsXml()); //} }catch (Exception bce) { Logger.Append(Severity.WARNING, "Error calling VSS BackupComplete() : " + bce.Message); } using (IVssAsync async = backup.GatherWriterStatus()){ async.Wait(); async.Dispose(); } Logger.Append(Severity.DEBUG, "6/6 Successfully shapshotted volume(s) "); foreach (ISnapshot sn in snapshots) { if (sn.Id == Guid.Empty) { continue; } sn.MountPoint = backup.GetSnapshotProperties(sn.Id).SnapshotDeviceObject; sn.TimeStamp = Utilities.Utils.GetUtcUnixTime(backup.GetSnapshotProperties(sn.Id).CreationTimestamp.ToUniversalTime()); /* * DirectoryInfo snapMountPoint = Directory.CreateDirectory( Path.Combine(Utilities.ConfigManager.GetValue("Backups.TempFolder"), "snapshot_"+sn.Id)); * Logger.Append(Severity.DEBUG, "Mounting shapshotted volume '"+sn.Name+"' to '"+snapMountPoint.FullName+"'"); * backup.ExposeSnapshot(sn.Id, null, VssVolumeSnapshotAttributes.ExposedLocally, snapMountPoint.FullName); * //sn.Path = snapMountPoint.FullName+Path.DirectorySeparatorChar; * //sn.Path = @"\\?\Volume{"+sn.Id+"}"+Path.DirectorySeparatorChar;*/ } } catch (Exception e) { try{ //backup.BackupComplete(); backup.AbortBackup(); } catch (Exception ae) { Logger.Append(Severity.ERROR, "Error trying to cancel VSS snapshot set : " + ae.Message); } // TODO !! report snapshoty failure to hub task Logger.Append(Severity.ERROR, "Error creating snapshot :'" + e.Message + " ---- " + e.StackTrace + "'. Backup will continue without snapshot. Backup of VSS components will fail. !TODO! report that to hub"); backup.Dispose(); throw new Exception(e.Message); } finally{ // TODO !!! reactivate dispose //backup.Dispose(); //pm.Revoke(); } return((ISnapshot[])snapshots.ToArray(typeof(ISnapshot))); } }
internal ISnapshot[] CreateVolumeSnapShot(List <FileSystem> volumeNames, SnapshotSupportedLevel level) { return(CreateVolumeSnapShot(volumeNames, null, level)); }
public ISnapshot[] CreateVolumeSnapShot(List <FileSystem> volumes, string[] specialObjects, SnapshotSupportedLevel level) { ArrayList snapshots = new ArrayList(); foreach (FileSystem volume in volumes) { Logger.Append(Severity.DEBUG, "1/1 create fake snapshot for volume " + volume.MountPoint); Snapshot sn = new Snapshot(); sn.Path = volume.MountPoint; //volume.Path; sn.MountPoint = volume.MountPoint; sn.Id = Guid.Empty; sn.TimeStamp = Utilities.Utils.GetUtcUnixTime(DateTime.UtcNow); snapshots.Add(sn); } Logger.Append(Severity.INFO, "Generated fake snapshots for " + volumes.Count + " volumes."); return((ISnapshot[])snapshots.ToArray(typeof(ISnapshot))); }
/// <summary> /// This method first looks if backup needs snapshotting drives. If so, then we do snapshot /// and use it to call BuildBackup method /// </summary> private void PrepareDrivesAndSnapshots() { SnapshotSupportedLevel snapLevel = ConvertBackupLevelToSnLevel(this.Level); Logger.Append(Severity.INFO, "Preparing backup for Task " + this.Id); HubNotificationEvent(this.Id, 701 /*snapshotting*/, "", ""); backupRootDrives = GetBackupInvolvedRootDrives(); Console.WriteLine("PrepareDrivesAndSnapshots()() backupRootDrives count=" + backupRootDrives.Count); string[] snapshotProvNames = new string[backupRootDrives.Count]; for (int i = 0; i < backupRootDrives.Count; i++) { if (backupRootDrives[i].RequiresSnapshot) { snapshotProvNames[i] = SnapshotProvider.GetDriveSnapshotProviderName(backupRootDrives[i].SystemDrive.MountPoint); } else { snapshotProvNames[i] = "NONE"; } } // the final list of all snapshot needed to perform the backup set backupSnapshots = new List <ISnapshot>(); // We try to make all snapshot in the shortest amount of time we can, // for data to be as consistent as possible foreach (string snapProv in snapshotProvNames.Distinct()) { Console.WriteLine("PrepareDrivesAndSnapshots() snapshotProvNames=" + snapProv); List <FileSystem> snapShotMemberDrives = new List <FileSystem>(); for (int i = 0; i < backupRootDrives.Count; i++) { if (snapshotProvNames[i] == snapProv) { snapShotMemberDrives.Add(backupRootDrives[i].SystemDrive); } } //Gather SpecialObjects (VSS writers) if any var spoList = from BasePath bp in this.BackupSet.BasePaths where bp.Type != null && bp.Type.ToLower().StartsWith("object:") //P2PBackup.Common.BasePath.PathType.OBJECT select bp.Path; ISnapshotProvider snapProvider = SnapshotProvider.GetProvider(snapProv); snapshotProviders.Add(snapProvider); snapProvider.LogEvent += LogReceivedEvent; ISnapshot[] volSnaps; try{ volSnaps = snapProvider.CreateVolumeSnapShot(snapShotMemberDrives, spoList.ToArray(), snapLevel); //if(snapProvider.Metadata != null) // Index.Header.ProviderMetadata.Add(new Tuple<string, Hashtable>(snapProvider.Name, snapProvider.Metadata.Metadata)); string volList = ""; foreach (FileSystem vol in snapShotMemberDrives) { volList += vol.MountPoint + ","; } Logger.Append(Severity.INFO, "Took snapshots (type " + snapProvider.Type + ") of drives " + volList); } catch (Exception e) { // we return a fake snapshot (snapshot path is the volume itself) string volList = ""; foreach (FileSystem vol in snapShotMemberDrives) { volList += vol.MountPoint + ","; } Logger.Append(Severity.WARNING, "Unable to take snapshot of drives " + volList + ", falling back to fake provider. Error was : " + e.Message + " --- " + e.StackTrace); HubNotificationEvent(this.Id, 805 /*cant snapshot*/, volList, e.Message); ISnapshotProvider nullProv = SnapshotProvider.GetProvider("NONE"); volSnaps = nullProv.CreateVolumeSnapShot(snapShotMemberDrives, spoList.ToArray(), snapLevel); } backupSnapshots.AddRange(volSnaps); snapProvider.LogEvent -= LogReceivedEvent; } //finally, add snapshot to corresponding BackupRootDrive Console.WriteLine("##### dumping rootdrives : "); foreach (BackupRootDrive rd in backupRootDrives) { foreach (ISnapshot snap in backupSnapshots) { if (/*snap.MountPoint*/ snap.Path == rd.SystemDrive.MountPoint) { rd.Snapshot = snap; Console.WriteLine("matched snapshot : " + snap.Path + ", snap mount path=" + snap.MountPoint); // let's change paths and excluded paths to their snapshotted values foreach (BasePath bp in rd.Paths) { //bp.Path = snap.Path + bp.Path; /*if(snap.Name == "/") * bp.Path = snap.Path; * else * bp.Path = bp.Path.Replace(snap.Name, snap.Path);*/ for (int i = 0; i < bp.ExcludedPaths.Count; i++) { //bp.ExcludedPaths[i] = snap.Path + bp.ExcludedPaths[i]; if (snap.Path == "/") { bp.ExcludedPaths[i] = snap.MountPoint + bp.ExcludedPaths[i]; } else { bp.ExcludedPaths[i] = bp.ExcludedPaths[i].Replace(snap.Path, snap.MountPoint); //bp.ExcludedPaths[i] = bp.ExcludedPaths[i].Replace(snap.Name, ""); //bp.ExcludedPaths[i] = Path.Combine(snap.Path, bp.ExcludedPaths[i]); //bp.ExcludedPaths[i] = Path.GetFullPath(bp.ExcludedPaths[i]); } } } break; } } Console.WriteLine("BackupRootDrive id=" + rd.ID + ", mount=" + rd.SystemDrive.MountPoint /*+", snapshot= "+rd.snapshot.Path*/); foreach (BasePath p in rd.Paths) { Console.WriteLine("\t p=" + p.Path + ", excludes : "); foreach (string s in p.ExcludedPaths) { Console.WriteLine("\t excluded " + s); } Console.WriteLine("\t\t, include patterns : "); foreach (string s in p.IncludePolicy) { Console.WriteLine("\t match " + s); } } } Console.WriteLine("##### #####"); foreach (BackupRootDrive rds in backupRootDrives) { Logger.Append(Severity.DEBUG, "Drive '" + rds.SystemDrive.OriginalMountPoint + "' was snapshotted to '" + rds.Snapshot.MountPoint + "' using provider '" + rds.Snapshot.Type + "' with timestamp " + rds.Snapshot.TimeStamp + " (" + Utils.GetLocalDateTimeFromUnixTime(rds.Snapshot.TimeStamp) + ")"); } }