Beispiel #1
0
        public BtrfsNfo(BtrfsNfos nfos, string basePath, string relPath, string uuid, string parentUUID, long generation, long genAtCreation)
        {
            this.nfos = nfos;

            BasePath      = basePath;
            RelPath       = relPath;
            UUID          = uuid;
            ParentUUID    = parentUUID;
            Generation    = generation;
            GenAtCreation = genAtCreation;
        }
Beispiel #2
0
        async Task <BtrfsNfos> ReadBtrfsNfo(string path)
        {
            var nfos = new BtrfsNfos();

            {
                var res = await Toolkit.Exec("btrfs", new[] { "sub", "list", path }, ct, development);

                foreach (var x in res.output.Lines())
                {
                    var q = x.IndexOf("path ");
                    if (q != -1)
                    {
                        var relpath        = x.Substring(q + "path ".Length);
                        var subvolFullpath = Path.Combine(path, relpath);

                        var subvolInfo = await GetSubVolumeInfo(path, subvolFullpath, ct);

                        nfos.Add(path, relpath, subvolInfo.uuid, subvolInfo.parentUUID, subvolInfo.generation, subvolInfo.genAtCreation);
                    }
                }
            }

            return(nfos);
        }
Beispiel #3
0
        public Task Run(string[] args)
        {
            if (!ParseArgs(args))
            {
                PrintUsage();
                Environment.Exit(1);
            }

            var cts = new CancellationTokenSource();
            var ct  = cts.Token;

            Console.CancelKeyPress += (s, e) =>
            {
                e.Cancel = true;
                cts.Cancel();
            };

            return(Task.Run(async() =>
            {
                var res = await Toolkit.Exec("btrfs", new[] { "sub", "list", SourcePath }, ct, development);

                var nfos = new BtrfsNfos();

                var sourcePaths = new List <string>();
                foreach (var x in res.output.Lines())
                {
                    var q = x.IndexOf("path ");
                    if (q != -1)
                    {
                        var relpath = x.Substring(q + "path ".Length);
                        var subvolFullpath = Path.Combine(SourcePath, relpath);

                        var subvolInfo = await GetSubVolumeInfo(subvolFullpath, ct);

                        nfos.Add(SourcePath, relpath, subvolInfo.uuid, subvolInfo.parentUUID, subvolInfo.generation, subvolInfo.genAtCreation);
                    }
                }

                #region log helper
                var indent = 0;
                Action <BtrfsNfo> logNfo = null;
                logNfo = (entry) =>
                {
                    var indentSpaces = " ".Repeat(2 * indent);

                    System.Console.WriteLine($@"
{indentSpaces}path:[{entry.Fullpath}]
{indentSpaces}uuid:[{entry.UUID}]
{indentSpaces}parentUUID:[{entry.ParentUUID}]=[{entry.Parent?.Fullpath}]
{indentSpaces}generation:[{entry.Generation}]
{indentSpaces}genAtCreation:[{entry.GenAtCreation}]
{indentSpaces}children:[{entry.Children.Count()}]");

                    ++indent;
                    foreach (var c in entry.Children.OrderBy(w => w.GenAtCreation))
                    {
                        logNfo(c);
                    }
                    --indent;
                };

                Action header1 = () => { System.Console.WriteLine("=".Repeat(78)); };
                Action header2 = () => { System.Console.WriteLine("-".Repeat(78)); };
                #endregion

                // log
                foreach (var entry in nfos.Entries.Where(r => r.Parent == null))
                {
                    logNfo(entry);
                }

                // plan work
                var workPlan = new List <BtrfsResynActionNfo>();

                Action <BtrfsNfo> planWorkAct = null;

                planWorkAct = (entry) =>
                {
                    var entryCounterPart = entry.CounterPart(TargetPath);

                    if (entry.Parent == null && !Directory.Exists(entryCounterPart))
                    {
                        var dstPath = Path.GetDirectoryName(entryCounterPart);
                        if (!Directory.Exists(dstPath))
                        {
                            workPlan.Add(new BtrfsResynActionNfo(BtrfsRsyncActionMode.ensurePath,
                                                                 Path.GetDirectoryName(entry.Fullpath),
                                                                 dstPath));
                        }
                        workPlan.Add(new BtrfsResynActionNfo(BtrfsRsyncActionMode.createSubvol, entry.Fullpath, entryCounterPart));
                    }

                    if (entry.Children.Any())
                    {
                        foreach (var(child, idx, isLast) in entry.Children.OrderBy(w => w.GenAtCreation).WithIndexIsLast())
                        {
                            var childCounterPart = child.CounterPart(TargetPath);
                            var childCounterPartExists = Directory.Exists(childCounterPart);

                            if (childCounterPartExists)
                            {
                                if (!SkipSubVolResync)
                                {
                                    workPlan.Add(new BtrfsResynActionNfo(BtrfsRsyncActionMode.rsync, child.Fullpath, childCounterPart));
                                }
                            }
                            else if (entry.Parent == null)
                            {
                                workPlan.Add(new BtrfsResynActionNfo(BtrfsRsyncActionMode.rsync, child.Fullpath, entryCounterPart));
                                workPlan.Add(new BtrfsResynActionNfo(BtrfsRsyncActionMode.snap, entryCounterPart, childCounterPart));
                            }

                            if (child.Children.Any())
                            {
                                planWorkAct(child);
                            }

                            if (isLast)
                            {
                                workPlan.Add(new BtrfsResynActionNfo(BtrfsRsyncActionMode.rsync, entry.Fullpath, entryCounterPart,
                                                                     entry.Children.Select(w => w.CounterPart(TargetPath))));
                            }
                        }
                    }
                    else
                    {
                        workPlan.Add(new BtrfsResynActionNfo(BtrfsRsyncActionMode.rsync, entry.Fullpath, entryCounterPart));
                    }
                };

                foreach (var entry in nfos.Entries.Where(r => r.Parent == null))
                {
                    planWorkAct(entry);
                }

                #region log workplane
                {
                    System.Console.WriteLine();
                    header1();
                    System.Console.WriteLine($"WORKPLAN");
                    header1();
                    foreach (var wp in workPlan)
                    {
                        System.Console.WriteLine(wp.ToString());
                    }
                }
                #endregion

                #region dryrun log helper
                Action <string, IEnumerable <string> > dryRunProg = (p, a) =>
                {
                    System.Console.WriteLine($"{p} {string.Join(" ", a)}");
                };
                #endregion

                System.Console.WriteLine();
                header1();
                System.Console.WriteLine($"RUNNING");
                header1();

                foreach (var wp in workPlan)
                {
                    switch (wp.Mode)
                    {
                    case BtrfsRsyncActionMode.ensurePath:
                        {
                            // TODO: acl and permission set
                            var cmdprog = "mkdir";
                            var cmdargs = new List <string>()
                            {
                                "-p", wp.DestPath
                            };
                            if (RunMode == RunMode.dryRun)
                            {
                                dryRunProg(cmdprog, cmdargs);
                            }
                            else
                            {
                                var cmdres = await Toolkit.ExecNoRedirect(cmdprog, cmdargs, ct, development);
                            }
                        }
                        break;

                    case BtrfsRsyncActionMode.createSubvol:
                        {
                            var cmdprog = "btrfs";
                            var cmdargs = new List <string>()
                            {
                                "sub", "create", wp.DestPath
                            };
                            if (RunMode == RunMode.dryRun)
                            {
                                dryRunProg(cmdprog, cmdargs);
                            }
                            else
                            {
                                var cmdres = await Toolkit.ExecNoRedirect(cmdprog, cmdargs, ct, development);
                            }
                        }
                        break;

                    case BtrfsRsyncActionMode.rsync:
                        {
                            var cmdprog = "rsync";
                            var cmdargs = new List <string>();
                            cmdargs.Add("-Aav");
                            cmdargs.Add("--delete");
                            foreach (var excl in wp.rsyncExclusions)
                            {
                                cmdargs.Add($"--exclude={excl}");
                            }
                            cmdargs.Add(wp.SourcePath + "/");
                            cmdargs.Add(wp.DestPath + "/");
                            if (RunMode == RunMode.dryRun)
                            {
                                dryRunProg(cmdprog, cmdargs);
                            }
                            else
                            {
                                var cmdres = await Toolkit.ExecNoRedirect(cmdprog, cmdargs, ct, development);
                            }
                        }
                        break;

                    case BtrfsRsyncActionMode.snap:
                        {
                            var cmdprog = "btrfs";
                            var cmdargs = new List <string>()
                            {
                                "sub", "snap", wp.SourcePath, wp.DestPath
                            };
                            if (RunMode == RunMode.dryRun)
                            {
                                dryRunProg(cmdprog, cmdargs);
                            }
                            else
                            {
                                var cmdres = await Toolkit.ExecNoRedirect(cmdprog, cmdargs, ct, development);
                            }
                        }
                        break;
                    }
                }
            }));
        }