Exemple #1
0
        private async Task MountDisks(BobApiClient bobApiClient)
        {
            var disks = await FindDisks();

            foreach (var disk in disks)
            {
                foreach (var volume in disk.Volumes)
                {
                    if (neededInfoStorage.ShouldBeProcessed(volume))
                    {
                        await disksMounter.MountVolume(volume, bobApiClient);

                        if (!neededInfoStorage.IsProtected(volume))
                        {
                            var bobPath = neededInfoStorage.FindBobPath(volume);
                            if (bobPath != null)
                            {
                                await bobPathPreparer.PrepareBobPath(bobPath);
                            }
                            else
                            {
                                logger.LogInformation($"No bobpath found for {volume}");
                            }
                        }
                    }
                }
            }
        }
Exemple #2
0
        private async Task <bool> TryCleanPreviousData(Volume volume, BobApiClient bobApiClient, MountPath path)
        {
            int count = 0;

            await TryStopBobdisk(volume, bobApiClient);

            while (count++ < configuration.MaxUmountRetries)
            {
                try
                {
                    var disks = await disksFinder.FindDisks();

                    if (disks.Any(d => d.Volumes.Count > 0 && d.Volumes.Any(v => v.MountPath?.Equals(path) == true && v.IsMounted)))
                    {
                        logger.LogInformation($"Trying to unmount previous disks in {path}");
                        await processInvoker.InvokeSudoProcess("umount", path.ToString());

                        logger.LogInformation($"Successfully umounted previous disks in {path}");
                    }
                    return(true);
                }
                catch (ProcessFailedException e) when(e.ExitCode == 32)
                {
                    await Task.Delay(1000);
                }
            }
Exemple #3
0
        private async Task <List <RestartInfo?> > CopyAliensFromNode(NodeWithDirs node, List <NodeWithDirs> nodes, Configuration config)
        {
            var result = new List <RestartInfo?>();

            var client = new BobApiClient(node.Uri);
            var disks  = await client.GetDisksToMonitor();

            var alienDisk = disks.FirstOrDefault(d => d.Path == node.AlienDir.Path).Name;

            if (alienDisk == null)
            {
                return(result);
            }

            await client.StopDisk(alienDisk);

            await client.StartDisk(alienDisk);

            var tasks = new List <Task <RestartInfo?[]> >();

            foreach (var alienNode in node.AlienDir.Nodes)
            {
                tasks.Add(CopyAlien(alienNode, nodes, config));
            }
            return(await Task.WhenAll(tasks).ContinueWith(t => t.Result.SelectMany(_ => _).ToList()));
        }
Exemple #4
0
        private static async Task <(long max, long total)> CollectRecordsFromNodes(ClusterRecordsCounter crc)
        {
            var apiByName = new Dictionary <string, BobApiClient>();
            var vdisks    = new List <VDisk>();

            foreach (var node in configuration.Nodes)
            {
                try
                {
                    var api    = new BobApiClient(node.Address);
                    var status = await api.GetStatus();

                    if (status == null)
                    {
                        logger.LogError($"Node {node.Address} not available");
                        continue;
                    }
                    apiByName.Add(status?.Name, api);
                    foreach (var vdisk in status?.VDisks)
                    {
                        if (!vdisks.Any(vd => vd.Id == vdisk.Id))
                        {
                            vdisks.Add(vdisk);
                        }
                    }
                }
                catch (Exception e)
                {
                    logger.LogError($"Error getting info from node {node.Address}, {e.Message}");
                }
            }
            return(await crc.CountRecords(apiByName, vdisks));
        }
Exemple #5
0
 public async Task CheckAndUpdate(BobApiClient bobApiClient)
 {
     await PrepareDisks();
     await FormatDisks();
     await MountDisks(bobApiClient);
     await AlterFSTab();
 }
Exemple #6
0
        private static async Task <Configuration> GetConfiguration(BobApiClient bobApiClient)
        {
            logger.LogInformation("Reading configuration...");
            var configuration = serviceProvider.GetRequiredService <Configuration>();

            try
            {
                await configuration.ReadFromFile(configFile);

                await configuration.AddEntriesFromBob(bobApiClient);

                await configuration.SaveToFile(configFile);

                return(configuration);
            }
            catch (Exception e)
            {
                logger.LogError($"Exception while getting info from config: {e.Message}{Environment.NewLine}{e.StackTrace}");
                throw;
            }
            finally
            {
                logger.LogInformation("Reading configuration done");
            }
        }
Exemple #7
0
    public async Task <(long unique, long withReplicas)> CountRecordsInCluster(Uri baseNode)
    {
        using var api = new BobApiClient(baseNode);
        var nodeObj = await api.GetStatus();

        if (nodeObj is null)
        {
            throw new Exception("Failed to get node status");
        }
        var vdisks = nodeObj.Value.VDisks;
        var nodes  = await api.GetNodes();

        if (nodes is null)
        {
            throw new Exception("Failed to get nodes information");
        }

        var apiByName = nodes.ToDictionary(n => n.Name, n =>
        {
            var url  = new Uri($"{baseNode.Scheme}://{n.Address}");
            var addr = $"{baseNode.Scheme}://{url.Host}:{baseNode.Port}";
            logger.LogInformation($"Found cluster node {addr}");
            return(new BobApiClient(new Uri(addr)));
        });

        return(await CountRecords(apiByName, vdisks));
    }
Exemple #8
0
        private async Task <NodeWithDirs> CreateNode(ConnectionInfo info)
        {
            var api    = new BobApiClient(info.Uri);
            var status = await api.GetStatus();

            if (status == null)
            {
                logger.LogWarning($"Failed to get status from {info.Uri}");
                return(null);
            }
            var diskDirs = new List <DiskDir>();

            foreach (var vDisk in status?.VDisks)
            {
                var dirs = await api.GetDirectories(vDisk);

                foreach (var replica in vDisk.Replicas)
                {
                    if (replica.Node != status?.Name)
                    {
                        continue;
                    }
                    var parentPath = replica.Path;
                    var name       = $"path {replica.Path} on node {info.Uri}";
                    logger.LogInformation($"Reading disk structure from {name}");
                    if (dirs == null)
                    {
                        logger.LogWarning($"Failed to get disk structure for {name}");
                        continue;
                    }
                    var baseDir = dirs.FirstOrDefault(re => re.Path.TrimEnd('/') == replica.Path.TrimEnd('/'));
                    if (baseDir.Path != null)
                    {
                        logger.LogInformation($"Found dir for {name}");
                        var dir = nodeStructureCreator.ParseDisk(replica.Disk, baseDir, info);
                        if (dir != null)
                        {
                            logger.LogInformation($"Successfully read structure of {name}");
                            diskDirs.Add(dir);
                        }
                        else
                        {
                            logger.LogWarning($"Structure of {name} can't be parsed");
                        }
                    }
                    else
                    {
                        logger.LogWarning($"Dir for {name} no found");
                    }
                }
            }
            var alienDir = await api.GetAlienDirectory();

            var alien = nodeStructureCreator.ParseAlien(alienDir, info);

            return(new NodeWithDirs(info, status?.Name, diskDirs, alien));
        }
Exemple #9
0
        public async Task CopyDataFromReplica(BobApiClient bobApiClient, BobDisk bobDisk)
        {
            if (configuration.PathToDiskStatusAnalyzer == null || !File.Exists(configuration.PathToDiskStatusAnalyzer))
            {
                logger.LogInformation($"DiskStatusAnalyzer path ({configuration.PathToDiskStatusAnalyzer}) is invalid, skipping copy");
                return;
            }
            var status = await bobApiClient.GetStatus();

            if (status is null)
            {
                logger.LogError($"Failed to get status from {bobApiClient}");
                return;
            }
            var destName = status?.Name;
            var diskName = bobDisk.DiskNameInBob;

            bool IsCurrent(Replica replica) => replica.Node == destName && replica.Disk == diskName;

            var vdisks = status?.VDisks.Where(vd => vd.Replicas.Any(IsCurrent));

            if (!vdisks.Any())
            {
                logger.LogError($"VDisks with replica ({diskName}, {destName}) not found");
                return;
            }
            foreach (var vdisk in vdisks)
            {
                var bobPath = Path.Combine(bobDisk.BobPath.Path, "bob");
                await TryCreateDir(bobPath);
                await TryCreateDir(Path.Combine(bobPath, vdisk.Id.ToString()));

                foreach (var replica in vdisk.Replicas)
                {
                    if (replica.Node == destName)
                    {
                        continue;
                    }
                    logger.LogInformation($"Trying to copy {vdisk} from {replica.Node} to {destName}");
                    try
                    {
                        await PerformCopy(replica.Node, destName, vdisk.Id);

                        logger.LogInformation($"Successfully copied {vdisk} from {replica.Node} to {destName}");
                        break;
                    }
                    catch (Exception e)
                    {
                        logger.LogError($"Failed to copy {vdisk} from {replica.Node} to {destName}: {e.Message}");
                    }
                }
            }
        }
Exemple #10
0
        public async Task <IEnumerable <BobDisk> > GenerateConfigFromBob(BobApiClient bobApiClient)
        {
            var disks = await bobApiClient.GetDisksToMonitor();

            if (disks == null)
            {
                logger.LogError($"Failed to get bob disks from {bobApiClient}");
                return(Enumerable.Empty <BobDisk>());
            }
            var physicalDisks = await disksFinder.FindDisks();

            var infos = disks.Where(d => d.IsActive).Select(d => FindInfo(d, physicalDisks)).Where(i => i != null);

            return(infos);
        }
Exemple #11
0
        public async Task StartDisks(BobApiClient bobApiClient)
        {
            var disksToStart = configuration.MonitoringEntries;
            var disks        = await disksFinder.FindDisks();

            foreach (var i in disksToStart)
            {
                var inactiveDisks = await bobApiClient.GetInactiveDisks();

                if (inactiveDisks == null)
                {
                    return;
                }
                if (!inactiveDisks.Any(d => d.Name == i.DiskNameInBob))
                {
                    continue;
                }

                var disk   = disks.FirstOrDefault(d => d.Volumes.Any(v => v.MountPath.Equals(i.MountPath) && v.IsMounted));
                var volume = disk?.Volumes.First(v => v.MountPath.Equals(i.MountPath) && v.IsMounted);
                if (disks.Count == 0 ||
                    !disks.Any(d => !d.NoVolumes && d.Volumes.Any(v => v.MountPath.Equals(i.MountPath) && v.IsMounted && !v.IsReadOnly)))
                {
                    continue;
                }

                logger.LogInformation($"Trying to start disk {i}");
                if (!configuration.KnownUuids.Contains(volume.UUID))
                {
                    await disksCopier.CopyDataFromReplica(bobApiClient, i);
                }
                configuration.SaveUUID(await disksMonitor.GetUUID(i));
                logger.LogInformation($"Starting bobdisk {i}...");
                int retry = 0;
                while (!await bobApiClient.StartDisk(i.DiskNameInBob) && retry++ < configuration.StartRetryCount)
                {
                    logger.LogWarning($"Failed to start bobdisk in try {retry}, trying again");
                }
                if (retry == configuration.StartRetryCount)
                {
                    logger.LogError($"Failed to start bobdisk {i}");
                }
                else
                {
                    logger.LogInformation($"Bobdisk {i} started");
                }
            }
        }
Exemple #12
0
        private static async Task DeleteOldPartitions(Uri uri, VDisk vDisk, List <string> partitions)
        {
            using var api = new BobApiClient(uri);
            foreach (var partition in partitions)
            {
                var partitionObject = await api.GetPartition(vDisk, partition);

                if (partitionObject is null)
                {
                    LogError($"Failed to get partition {partition} on {vDisk}");
                }
                else if (GetDateTimeFromTimestamp(partitionObject?.Timestamp) < configuration.Threshold)
                {
                    await api.DeletePartition(vDisk, partitionObject?.Timestamp);

                    LogInfo($"Deleted partition {partition} on {vDisk}");
                }
            }
        }
Exemple #13
0
        private static async Task RemoveOldPartitions()
        {
            if (configuration?.Valid != true)
            {
                LogError("Bad configuration");
                return;
            }

            foreach (var node in configuration.Node)
            {
                using var api = new BobApiClient(node.Address);
                var status = await api.GetStatus();

                if (status == null)
                {
                    continue;
                }
                foreach (var vDisk in status?.VDisks)
                {
                    foreach (var replica in vDisk.Replicas)
                    {
                        if (replica.Node == status?.Name)
                        {
                            LogInfo($"Processing replica of vdisk {vDisk.Id} on node {node}");
                            var partitions = await api.GetPartitions(vDisk);

                            if (partitions == null)
                            {
                                LogError($"Partitions for {vDisk} not found");
                            }
                            else
                            {
                                LogInfo($"Found {partitions.Count} partitions on {vDisk}");
                                await DeleteOldPartitions(node.Address, vDisk, partitions);
                            }
                        }
                    }
                }
            }
        }
Exemple #14
0
        public async Task AddEntriesFromBob(BobApiClient bobApiClient)
        {
            var disks = await disksFinder.FindDisks();

            var infos = await configGenerator.GenerateConfigFromBob(bobApiClient);

            foreach (var i in infos)
            {
                logger.LogInformation($"Received {i} from bob");
                var conflict = MonitoringEntries.FirstOrDefault(bd => bd.DiskNameInBob == i.DiskNameInBob && bd.BobPath.Equals(i.BobPath) && !bd.Equals(i));
                if (conflict != null)
                {
                    logger.LogWarning($"Conflict: disk from bob {i} conflicts with disk from config {conflict}");
                    continue;
                }
                var uuid = disks.SelectMany(d => d.Volumes).FirstOrDefault(v => v.PhysicalId.Equals(i.PhysicalId) && v.IsFormatted)?.UUID;
                if (uuid != null)
                {
                    SaveUUID(uuid);
                }
                MonitoringEntries.Add(i);
            }
        }
Exemple #15
0
        public async Task MountVolume(Volume volume, BobApiClient bobApiClient)
        {
            if (volume.IsMounted && !volume.IsReadOnly)
            {
                logger.LogDebug($"{volume} is already mounted");
                return;
            }
            if (!volume.Mountable)
            {
                logger.LogDebug($"{volume} can't be mounted");
                return;
            }

            var mountPath = neededInfoStorage.FindMountPath(volume);

            if (mountPath != null)
            {
                var path = mountPath?.Path;
                if (!Directory.Exists(path))
                {
                    await processInvoker.InvokeSudoProcess("mkdir", path);
                }
                if (await TryCleanPreviousData(volume, bobApiClient, mountPath.Value) && !volume.IsMounted)
                {
                    logger.LogInformation($"Mounting {volume} to {mountPath}");
                    await processInvoker.InvokeSudoProcess("mount", volume.DevPath.Path, path);

                    await processInvoker.SetDirPermissionsAndOwner(path, configuration.MountPointPermissions, configuration.MountPointOwner);

                    logger.LogInformation($"Successfully mounted {volume} to {mountPath}");
                }
            }
            else
            {
                logger.LogInformation($"No mount path found for {volume}");
            }
        }