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()); }
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)); }
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(); })); }
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 })); }
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 static Task <Either <Error, TIn> > ToEitherRight <TIn>(this TIn right) { return(Prelude.RightAsync <Error, TIn>(right).ToEither()); }