Example #1
0
        private static Task <Either <PowershellFailure, VMStorageSettings> > ConfigToVMStorageSettings(MachineConfig config, HostSettings hostSettings)
        {
            var projectName       = Prelude.Some("default");
            var environmentName   = Prelude.Some("default");
            var dataStoreName     = Prelude.Some("default");
            var storageIdentifier = Option <string> .None;

            var names = new StorageNames()
            {
                ProjectName     = projectName,
                EnvironmentName = environmentName,
                DataStoreName   = dataStoreName,
            };

            if (!string.IsNullOrWhiteSpace(config.VM.Slug))
            {
                storageIdentifier = Prelude.Some(config.VM.Slug);
            }

            return(ResolveStorageBasePath(names, hostSettings.DefaultDataPath).MapAsync(path => new VMStorageSettings
            {
                StorageNames = names,
                StorageIdentifier = storageIdentifier,
                VMPath = path
            }));
        }
Example #2
0
        private static Task <Either <PowershellFailure, string> > JoinPathAndProject(string dsPath, string projectName)
        {
            var result = dsPath;

            if (projectName != "default")
            {
                result = Path.Combine(dsPath, $"haipa_p{projectName}");
            }

            return(Prelude.RightAsync <PowershellFailure, string>(result).ToEither());
        }
Example #3
0
        public static (StorageNames Names, Option <string> StorageIdentifier) PathToStorageNames(string path, string defaultPath)
        {
            var projectName       = Prelude.Some("default");
            var environmentName   = Prelude.Some("default");
            var dataStoreName     = Option <string> .None;
            var dataStorePath     = Option <string> .None;
            var storageIdentifier = Option <string> .None;

            if (path.StartsWith(defaultPath, StringComparison.InvariantCultureIgnoreCase))
            {
                dataStoreName = Prelude.Some("default");
                dataStorePath = defaultPath;
            }

            if (dataStorePath.IsSome)
            {
                var pathAfterDS = path.Remove(0, dataStorePath.ValueUnsafe().Length).TrimStart('\\');

                var pathRoot = Path.GetPathRoot(pathAfterDS);
                if (pathRoot.StartsWith("haipa_p"))
                {
                    projectName = pathRoot.Remove(0, "haipa_p".Length);
                }

                var idCandidate = pathAfterDS;

                if (idCandidate.Contains(Path.DirectorySeparatorChar))
                {
                    idCandidate = Path.GetDirectoryName(pathAfterDS);
                }

                if (!string.IsNullOrWhiteSpace(idCandidate) && pathRoot != idCandidate)
                {
                    storageIdentifier = idCandidate;
                }
            }

            var names = new StorageNames
            {
                DataStoreName   = dataStoreName,
                ProjectName     = projectName,
                EnvironmentName = environmentName
            };

            return(names, storageIdentifier);
        }
Example #4
0
        public static Task <Either <PowershellFailure, Option <VMStorageSettings> > > DetectVMStorageSettings(
            Option <TypedPsObject <VirtualMachineInfo> > optionalVmInfo, HostSettings hostSettings,
            Func <string, Task> reportProgress)
        {
            return(optionalVmInfo
                   .MatchAsync(
                       Some: s =>
            {
                var namesAndId = PathToStorageNames(s.Value.Path, hostSettings.DefaultDataPath);

                var settings =
                    (from resolvedPath in ResolveStorageBasePath(namesAndId.Names, hostSettings.DefaultDataPath)
                     from storageSettings in ComparePath(resolvedPath, s.Value.Path,
                                                         namesAndId.StorageIdentifier)
                     select storageSettings);

                return settings.Bind(e => e.Match(
                                         Right: matchedPath => Prelude.RightAsync <PowershellFailure, VMStorageSettings>(
                                             new VMStorageSettings
                {
                    StorageNames = namesAndId.Names,
                    StorageIdentifier = namesAndId.StorageIdentifier,
                    VMPath = matchedPath,
                }).ToEither(),
                                         Left: async(l) =>
                {
                    //current behaviour is to soft fail by disabling storage changes
                    //however later we should add a option to strictly fail on all operations
                    await reportProgress(
                        "Invalid machine storage settings. Storage management is disabled.");

                    return Prelude.Right <PowershellFailure, VMStorageSettings>(
                        new VMStorageSettings
                    {
                        StorageNames = namesAndId.Names,
                        StorageIdentifier = namesAndId.StorageIdentifier,
                        VMPath = s.Value.Path,
                        Frozen = true
                    }
                        );
                })).MapAsync(r => r.ToSome().ToOption());
            },
                       None: () => Option <VMStorageSettings> .None));
        }
Example #5
0
        private static Task <Either <PowershellFailure, string> > ComparePath(string firstPath, string secondPath, Option <string> storageIdentifier)
        {
            return(storageIdentifier.ToEither(new PowershellFailure {
                Message = "unknown VM storage identifier"
            })
                   .BindAsync(id =>
            {
                var fullPath = Path.Combine(firstPath, id);

                if (!secondPath.Equals(fullPath, StringComparison.InvariantCultureIgnoreCase))
                {
                    return Prelude
                    .LeftAsync <PowershellFailure, string>(new PowershellFailure {
                        Message = "Path calculation failure"
                    })
                    .ToEither();
                }
                return Prelude
                .RightAsync <PowershellFailure, string>(firstPath)
                .ToEither();
            }));
        }
Example #6
0
        private static Task <Either <PowershellFailure, VMStorageSettings> > EnsureStorageId(VMStorageSettings first, VMStorageSettings second, Func <Task <Either <PowershellFailure, string> > > idGeneratorFunc)
        {
            if (second.Frozen)
            {
                return(Prelude.RightAsync <PowershellFailure, VMStorageSettings>(second).ToEither());
            }


            return(first.StorageIdentifier.MatchAsync(
                       None:
                       () => second.StorageIdentifier.MatchAsync(
                           None: idGeneratorFunc,
                           Some: s => Prelude.RightAsync <PowershellFailure, string>(s).ToEither()),
                       Some: s => Prelude.RightAsync <PowershellFailure, string>(s).ToEither()
                       ).MapAsync(storageIdentifier =>

                                  new VMStorageSettings
            {
                StorageNames = first.StorageNames,
                StorageIdentifier = storageIdentifier,
                VMPath = first.VMPath
            }));
        }
Example #7
0
 public static IImmutableList <Either <T, Exception> > ToList <T>(this TryOption <T> self) =>
 Prelude.toList(self.AsEnumerable());
Example #8
0
 public static async Task <Option <A> > lastOrNoneAsync <FOLD, F, A>(F fa) where FOLD : FoldableAsync <F, A> =>
 (await toSeqAsync <FOLD, F, A>(fa))
 .Map(x => Prelude.Some(x))
 .DefaultIfEmpty(Option <A> .None)
 .LastOrDefault();
Example #9
0
 public static Option <A> lastOrNone <FOLD, F, A>(F fa) where FOLD : struct, Foldable <F, A> =>
 toSeq <FOLD, F, A>(fa)
 .Map(x => Prelude.Some(x))
 .DefaultIfEmpty(Option <A> .None)
 .LastOrDefault();
 public static Either <L, R> ForceLeft <L, R>(this Either <L, R> either, Func <R, L> force)
 {
     return(either.Bind(
                _ => Prelude.Left <L, R>(force(_))));
 }
 public static Either <L, R> ForceRight <L, R>(this Either <L, R> either, Func <L, R> force)
 {
     return(either.BindLeft(
                _ => Prelude.Right <L, R>(force(_))));
 }
 /// <summary>
 /// Safely use a disposable resource
 /// </summary>
 /// <param name="Acq">Acquire resource</param>
 /// <param name="Use">Use resource</param>
 public static Eff <R> Use <H, R>(this Eff <H> Acq, Func <H, Eff <R> > Use) where H : IDisposable =>
 Prelude.use(Acq, Use);
 public static Seq <B> rights <CHOICE, CH, A, B>(Seq <CH> ma)
     where CHOICE : struct, ChoiceUnsafe <CH, A, B> =>
 Prelude.toSeq(rights <CHOICE, CH, A, B>(ma.AsEnumerable()));
Example #14
0
 public static ImmutableArray <Either <T, Exception> > ToArray <T>(this TryOption <T> self) =>
 Prelude.toArray(self.AsEnumerable());
Example #15
0
 public T[] ToArray() =>
 Prelude.toArray(AsEnumerable());
Example #16
0
 public Either <L, T> ToEither <L>(Func <L> Left) =>
 IsSome
         ? Prelude.Right <L, T>(Value)
         : Prelude.Left <L, T>(Left());
Example #17
0
 public static async Task <Seq <B> > rightsUnsafeAsync <CHOICE, CH, A, B>(Seq <CH> ma)
     where CHOICE : struct, ChoiceUnsafeAsync <CH, A, B> =>
 Prelude.toSeq(await rightsUnsafeAsync <CHOICE, CH, A, B>(ma.AsEnumerable()).ConfigureAwait(false));
Example #18
0
 public Either <L, T> ToEither <L>(L defaultLeftValue) =>
 IsSome
         ? Prelude.Right <L, T>(Value)
         : Prelude.Left <L, T>(defaultLeftValue);
Example #19
0
 public Seq <A> ToSeq() =>
 Prelude.Seq(this);
Example #20
0
 /// <summary>
 /// Safe pop
 /// </summary>
 /// <returns>Tuple of popped stack and optional top-of-stack value</returns>
 public Tuple <Stck <T>, Option <T> > TryPop() =>
 Count > 0
         ? Tuple.Create(tail, Prelude.Some(value))
         : Tuple.Create <Stck <T>, Option <T> >(this, Prelude.None);
 /// <summary>
 /// Safely use a disposable resource
 /// </summary>
 /// <param name="Acq">Acquire resource</param>
 /// <param name="Use">Use resource</param>
 public static Eff <RT, R> Use <RT, H, R>(this Eff <RT, H> Acq, Func <H, Eff <RT, R> > Use)
     where RT : struct, HasCancel <RT>
     where H : IDisposable =>
 Prelude.use(Acq, Use);
 public IImmutableList <T> ToList() =>
 Prelude.toList(AsEnumerable());
Example #23
0
        private static Task <Either <PowershellFailure, VMDriveStorageSettings> > DriveConfigToDriveStorageSettings(int index,
                                                                                                                    VirtualMachineDriveConfig driveConfig, VMStorageSettings storageSettings, HostSettings hostSettings)
        {
            const int controllerNumber   = 0;     //currently this will not be configurable, but keep it here at least as constant
            var       controllerLocation = index; //later, when adding controller config support, we will have to add a logic to

            //set location relative to the free slots for each controller


            //if it is not a vhd, we only need controller settings
            if (driveConfig.Type != VirtualMachineDriveType.VHD)
            {
                VMDriveStorageSettings result;
                if (driveConfig.Type == VirtualMachineDriveType.DVD)
                {
                    result = new VMDVdStorageSettings
                    {
                        ControllerNumber   = controllerNumber,
                        ControllerLocation = controllerLocation,
                        Type = VirtualMachineDriveType.DVD
                    };
                }
                else
                {
                    result = new VMDriveStorageSettings
                    {
                        ControllerNumber   = controllerNumber,
                        ControllerLocation = controllerLocation,
                        Type = driveConfig.Type.GetValueOrDefault(VirtualMachineDriveType.PHD)
                    };
                }

                return(Prelude.RightAsync <PowershellFailure, VMDriveStorageSettings>(result).ToEither());
            }

            //so far for the simple part, now the complicated case - a vhd disk...

            var projectName       = Prelude.Some("default");
            var environmentName   = Prelude.Some("default");
            var dataStoreName     = Prelude.Some("default");
            var storageIdentifier = Option <string> .None;

            var names = new StorageNames()
            {
                ProjectName     = projectName,
                EnvironmentName = environmentName,
                DataStoreName   = dataStoreName,
            };



            if (storageIdentifier.IsNone)
            {
                storageIdentifier = storageSettings.StorageIdentifier;
            }


            return
                ((from resolvedPath in ResolveStorageBasePath(names, hostSettings.DefaultVirtualHardDiskPath).ToAsync()
                  from identifier in storageIdentifier.ToEither(new PowershellFailure
            {
                Message = $"Unexpected missing storage identifier for disk '{driveConfig.Name}'."
            })
                  .ToAsync()
                  .ToEither().ToAsync()

                  let planned = new VMDiskStorageSettings
            {
                Type = driveConfig.Type.Value,
                StorageNames = names,
                StorageIdentifier = storageIdentifier,
                ParentPath = driveConfig.Template,
                Path = Path.Combine(resolvedPath, identifier),
                AttachPath = Path.Combine(Path.Combine(resolvedPath, identifier), $"{driveConfig.Name}.vhdx"),
                // ReSharper disable once StringLiteralTypo
                Name = driveConfig.Name,
                SizeBytes = driveConfig.Size.ToOption().Match(None: () => 1 * 1024L * 1024 * 1024,
                                                              Some: s => s * 1024L * 1024 * 1024),
                ControllerNumber = controllerNumber,
                ControllerLocation = controllerLocation
            }
                  select planned as VMDriveStorageSettings).ToEither());
        }
 public ImmutableArray <T> ToArray() =>
 Prelude.toArray(AsEnumerable());
Example #25
0
        static Dispatch()
        {
            ProcessName broadcast  = "broadcast";
            ProcessName leastBusy  = "least-busy";
            ProcessName random     = "random";
            ProcessName roundRobin = "round-robin";

            ProcessName first  = "first";
            ProcessName second = "second";
            ProcessName third  = "third";
            ProcessName last   = "last";

            var processes = fun((ProcessId leaf) =>
            {
                if (!leaf.IsValid)
                {
                    return(new ProcessId[0]);
                }
                if (leaf.IsSelection)
                {
                    return(leaf.GetSelection());
                }
                if (leaf.Head().Name == "disp")
                {
                    leaf = leaf.Skip(1);
                    if (!leaf.IsValid)
                    {
                        return(new ProcessId[0]);
                    }
                    return(getFunc(leaf.Head().Name)(leaf.Skip(1)));
                }
                return(new ProcessId[1] {
                    leaf
                });
            });

            // Broadcast
            Broadcast = register(broadcast, processes);

            // First
            First = register(first, leaf => processes(leaf).Take(1));

            // Second
            Second = register(second, leaf => processes(leaf).Skip(1).Take(1));

            // Third
            Third = register(third, leaf => processes(leaf).Skip(2).Take(1));

            // Last
            Last = register(last, leaf => processes(leaf).Reverse().Take(1));

            // Least busy
            LeastBusy = register(leastBusy, leaf =>
                                 processes(leaf)
                                 .Map(pid => Tuple(inboxCount(pid), pid))
                                 .OrderBy(tup => tup.Item1)
                                 .Map(tup => tup.Item2)
                                 .Take(1));

            // Random
            Random = register(random, leaf => {
                var workers = processes(leaf).ToArray();
                return(new ProcessId[1] {
                    workers[Prelude.random(workers.Length)]
                });
            });

            // Round-robin
            object            sync            = new object();
            Map <string, int> roundRobinState = Map.empty <string, int>();

            RoundRobin = register(roundRobin, leaf => {
                var key     = leaf.ToString();
                var workers = processes(leaf).ToArray();
                int index   = 0;
                lock (sync)
                {
                    roundRobinState = roundRobinState.AddOrUpdate(key, x => { index = x % workers.Length; return(x + 1); }, 0);
                }
                return(new ProcessId[1] {
                    workers[index]
                });
            });
        }
Example #26
0
        /// <summary>
        /// Static ctor
        /// Sets up the default roles
        /// </summary>
        static Role()
        {
            ProcessName first      = "role-first";
            ProcessName second     = "role-second";
            ProcessName third      = "role-third";
            ProcessName last       = "role-last";
            ProcessName next       = "role-next";
            ProcessName prev       = "role-prev";
            ProcessName broadcast  = "role-broadcast";
            ProcessName leastBusy  = "role-least-busy";
            ProcessName random     = "role-random";
            ProcessName roundRobin = "role-round-robin";

            var nextNode = fun((bool fwd) => fun((ProcessId leaf) =>
            {
                var self    = leaf.Take(1).Name;
                var isNext  = false;
                var nodeMap = Nodes(leaf);

                var nodes = fwd
                    ? nodeMap.Values.Append(nodeMap.Values)
                    : nodeMap.Values.Append(nodeMap.Values).Reverse(); //< TODO: Inefficient

                foreach (var node in nodes)
                {
                    if (isNext)
                    {
                        return(new[] { ProcessId.Top[node.NodeName].Append(leaf.Skip(1)) }.AsEnumerable());
                    }

                    if (node.NodeName == self)
                    {
                        isNext = true;
                    }
                }
                return(new ProcessId[0].AsEnumerable());
            }));

            // Next
            nextRoot = Dispatch.register(next, nextNode(true));

            // Prev
            prevRoot = Dispatch.register(prev, nextNode(false));

            // First
            First = Dispatch.register(first, leaf => NodeIds(leaf).Take(1));

            // Second
            Second = Dispatch.register(second, leaf => NodeIds(leaf).Skip(1).Take(1));

            // Third
            Third = Dispatch.register(third, leaf => NodeIds(leaf).Skip(2).Take(1));

            // Last
            Last = Dispatch.register(last, leaf => NodeIds(leaf).Reverse().Take(1));

            // Broadcast
            Broadcast = Dispatch.register(broadcast, NodeIds);

            // Least busy
            LeastBusy = Dispatch.register(leastBusy, leaf =>
                                          NodeIds(leaf)
                                          .Map(pid => Tuple(inboxCount(pid), pid))
                                          .OrderBy(tup => tup.Item1)
                                          .Map(tup => tup.Item2)
                                          .Take(1));

            // Random
            Random = Dispatch.register(random, leaf => {
                var workers = NodeIds(leaf).ToArray();
                return(new ProcessId[1] {
                    workers[Prelude.random(workers.Length)]
                });
            });

            // Round-robin
            object            sync            = new object();
            Map <string, int> roundRobinState = Map.empty <string, int>();

            RoundRobin = Dispatch.register(roundRobin, leaf => {
                var key     = leaf.ToString();
                var workers = NodeIds(leaf).ToArray();
                int index   = 0;
                lock (sync)
                {
                    roundRobinState = roundRobinState.AddOrUpdate(key, x => { index = x % workers.Length; return(x + 1); }, 0);
                }
                return(new ProcessId[1] {
                    workers[index]
                });
            });
        }
Example #27
0
 public Option <T> TryPeek() =>
 Count > 0
         ? Prelude.Some(value)
         : Prelude.None;
Example #28
0
 public Lst <T> ToList() =>
 Prelude.toList(AsEnumerable());