static bool GatherVolume(string volume, ref BackupOptions opts) { ZfsSnapshots snaps = new ZfsSnapshots(); if (!snaps.Filesystems().Contains(volume)) { Console.WriteLine("No snapshots for that volume, or no such volume."); return(false); } opts.Filesystem = volume; opts.Filename = volume.Replace('/', '_'); opts.IncrementalStartDate = null; opts.SnapshotDate = snaps.Snapshots(volume).OrderByDescending(s => s.Date).First().Date.ToString("yyyy-MM-dd"); return(true); }
static void ManageSnapshots() { var allSnaps = new ZfsSnapshots(); DateTime now = DateTime.Now; var toDelete = new List <ZfsSnapshots.SnapInfo>(); foreach (string fs in allSnaps.Filesystems()) { int count = 0; foreach (ZfsSnapshots.SnapInfo snap in allSnaps.Snapshots(fs)) { count++; int daysOld = (now - snap.Date).Days; // Keep 30 daily snapshots, // then 30 weekly snapshots, // Then monthly snapshots forever. bool delete = false; if ((count == 1) && (daysOld != 0) && !snap.NoAutoSnapshot) { Console.Write(ZfsSnapshots.Snapshot(fs)); Console.WriteLine("{0}\t{1}\t[NEW]", fs, DateTime.Now.ToString("yyyy-MM-dd")); count++; } Console.Write("{0}\t{1}\t{2} days old\t{3}B\t#{4}", snap.Filesystem, snap.Date.ToString("yyyy-MM-dd"), daysOld, snap.Size.Value.HumanNumber("F2"), count); var firstOfMonth = allSnaps.Snapshots(fs) .Select(e => e.Date) .Where(e => e.Year == snap.Date.Year) .Where(e => e.Month == snap.Date.Month) .OrderBy(e => e) .First(); if (count > 60) { // Keep only if the first snapshot of the month. if (snap.Date != firstOfMonth) { delete = true; } } else if (count > 30) { // Keep only if the first snapshot of the week or month. var firstOfWeek = allSnaps.Snapshots(fs) .Select(e => e.Date) .Where(e => e.Year == snap.Date.Year) .Where(e => e.GetWeekOfYear() == snap.Date.GetWeekOfYear()) .OrderBy(e => e) .First(); if ((snap.Date != firstOfWeek) && (snap.Date != firstOfMonth)) { delete = true; } } if (delete) { Console.Write("\t[delete]"); toDelete.Add(snap); } Console.WriteLine(); } } foreach (ZfsSnapshots.SnapInfo delete in toDelete) { Console.WriteLine("zfs destroy {0}", delete.Name); Console.WriteLine(ZfsSnapshots.Delete(delete)); } }
static void GatherVolumes(string mountPoint, List <BackupOptions> volumes) { IEnumerable <string> files = null; try { files = Directory.EnumerateFiles(mountPoint, "*.zfs*", System.IO.SearchOption.TopDirectoryOnly); } catch (DirectoryNotFoundException ex) { Console.WriteLine(ex.Message); } if (files.Count() == 0) { return; } string snapList = string.Join("\n", files.Where(s => !s.EndsWith("_partial")) .Select(s => new string( s.Take(s.LastIndexOf(".zfs")) .Skip(s.LastIndexOf(Path.DirectorySeparatorChar) + 1) .ToArray()))); ZfsSnapshots backups = new ZfsSnapshots(snapList); ZfsSnapshots snaps = new ZfsSnapshots(); var namesToFilesystems = new Dictionary <string, string>(); foreach (string name in backups.Filesystems()) { if (snaps.Filesystems().Contains(name.Replace('_', '/'))) { namesToFilesystems.Add(name, name.Replace('_', '/')); } else { IEnumerable <string> matches = snaps.Filesystems().Where(s => s.EndsWith("/" + name)); if (matches.Count() == 1) { namesToFilesystems.Add(name, matches.Single()); } else { Console.WriteLine("Backup filename \"{0}\" is ambiguous. Not sure what volume it's for. Skipping it.", name); } } } foreach (KeyValuePair <string, string> pair in namesToFilesystems) { var opts = new BackupOptions(); opts.Filename = pair.Key; opts.Filesystem = pair.Value; var newestBackup = backups.Snapshots(pair.Key).OrderByDescending(s => s.Date).First(); var newestSnapshot = snaps.Snapshots(pair.Value).OrderByDescending(s => s.Date).First(); opts.SnapshotDate = newestSnapshot.Date.ToString("yyyy-MM-dd"); try { ZfsSnapshots.SnapInfo snapForBackup = snaps.Snapshots(pair.Value).Where(s => s.Date == newestBackup.Date).Single(); if (newestSnapshot.Date == snapForBackup.Date) { Console.WriteLine("Backup file \"{0}\" is already current.", newestBackup.Name); opts.SnapshotDate = null; } else { opts.IncrementalStartDate = snapForBackup.Date.ToString("yyyy-MM-dd"); } } catch (Exception) { Console.WriteLine("Couldn't find a snapshot for backup file \"{0}\". Doing non-incremental backup.", newestBackup.Name); opts.IncrementalStartDate = null; } volumes.Add(opts); } }