Beispiel #1
0
        public async Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > GetInfoAsync(string vmName) =>
        (await _engine.GetObjectsAsync <VirtualMachineInfo>(PsCommandBuilder.Create()
                                                            .AddCommand("get-vm").AddArgument(vmName)).ConfigureAwait(false))
        .Apply(
            queryResult =>
        {
            return(queryResult.Match(
                       Left: l => l,
                       Right: r =>
            {
                var vmArray = r.ToArray();

                if (vmArray.Length > 1)
                {
                    return Prelude.Left <PowershellFailure, TypedPsObject <VirtualMachineInfo> >(
                        new PowershellFailure {
                        Message = $"VM name '{vmName}' is not unique."
                    });
                }

                if (vmArray.Length == 0)
                {
                    return Prelude.Left <PowershellFailure, TypedPsObject <VirtualMachineInfo> >(
                        new PowershellFailure {
                        Message = $"VM name '{vmName}' not found"
                    });
                }

                var vmInfo = vmArray[0];

                SetInfo(vmInfo);
                return vmInfo;
            }
                       ));
        });
Beispiel #2
0
        public static Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > CreateVirtualMachine(
            IPowershellEngine engine,
            string vmName,
            string storageIdentifier,
            string vmPath,
            int startupMemory)
        {
            var memoryStartupBytes = startupMemory * 1024L * 1024;


            return(engine.GetObjectsAsync <VirtualMachineInfo>(PsCommandBuilder.Create()
                                                               .AddCommand("New-VM")
                                                               .AddParameter("Name", storageIdentifier)
                                                               .AddParameter("Path", vmPath)
                                                               .AddParameter("MemoryStartupBytes", memoryStartupBytes)
                                                               .AddParameter("Generation", 2))
                   .MapAsync(x => x.Head).MapAsync(
                       result =>
            {
                engine.RunAsync(PsCommandBuilder.Create().AddCommand("Get-VMNetworkAdapter")
                                .AddParameter("VM", result.PsObject).AddCommand("Remove-VMNetworkAdapter"));

                return result;
            })
                   .BindAsync(info => RenameVirtualMachine(engine, info, vmName)));
        }
Beispiel #3
0
        private static Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > InsertConfigDriveDisk(
            string configDriveIsoPath,
            TypedPsObject <VirtualMachineInfo> vmInfo,
            IPowershellEngine engine)
        {
            return
                (from dvdDrive in GetOrCreateInfoAsync(vmInfo,
                                                       l => l.DVDDrives,
                                                       drive => drive.ControllerLocation == 63 && drive.ControllerNumber == 0,
                                                       () => engine.GetObjectsAsync <DvdDriveInfo>(
                                                           PsCommandBuilder.Create().AddCommand("Add-VMDvdDrive")
                                                           .AddParameter("VM", vmInfo.PsObject)
                                                           .AddParameter("ControllerNumber", 0)
                                                           .AddParameter("ControllerLocation", 63)
                                                           .AddParameter("PassThru"))
                                                       )

                 from _ in engine.RunAsync(PsCommandBuilder.Create()

                                           .AddCommand("Set-VMDvdDrive")
                                           .AddParameter("VMDvdDrive", dvdDrive.PsObject)
                                           .AddParameter("Path", configDriveIsoPath))

                 from vmInfoRecreated in vmInfo.RecreateOrReload(engine)
                 select vmInfoRecreated);
        }
Beispiel #4
0
        public static async Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > Disk(
            VirtualMachineDiskConfig diskConfig,
            IPowershellEngine engine,
            TypedPsObject <VirtualMachineInfo> vmInfo,
            MachineConfig vmConfig,
            Func <string, Task> reportProgress)
        {
            if (!File.Exists(diskConfig.Path))
            {
                await reportProgress($"Create VHD: {diskConfig.Name}").ConfigureAwait(false);

                await engine.RunAsync(PsCommandBuilder.Create().Script(
                                          $"New-VHD -Path \"{diskConfig.Path}\" -ParentPath \"{diskConfig.Template}\" -Differencing"),
                                      reportProgress : p => ReportPowershellProgress($"Create VHD {diskConfig.Name}", p, reportProgress)).ConfigureAwait(false);
            }

            await GetOrCreateInfoAsync(vmInfo,
                                       i => i.HardDrives,
                                       disk => diskConfig.Path.Equals(disk.Path, StringComparison.OrdinalIgnoreCase),
                                       async() =>
            {
                await reportProgress($"Add VHD: {diskConfig.Name}").ConfigureAwait(false);
                return(await engine.GetObjectsAsync <HardDiskDriveInfo>(PsCommandBuilder.Create()
                                                                        .AddCommand("Add-VMHardDiskDrive")
                                                                        .AddParameter("VM", vmInfo.PsObject)
                                                                        .AddParameter("Path", diskConfig.Path)).ConfigureAwait(false));
            }).ConfigureAwait(false);

            return(vmInfo.Recreate());
        }
 public static Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > Reload(this TypedPsObject <VirtualMachineInfo> vmInfo, IPowershellEngine engine)
 {
     return(engine.GetObjectsAsync <VirtualMachineInfo>(
                new PsCommandBuilder().AddCommand("Get-VM").AddParameter("Id", vmInfo.Value.Id))
            .BindAsync(r => r.HeadOrNone().ToEither(new PowershellFailure {
         Message = "Failed to refresh VM data"
     })));
 }
Beispiel #6
0
        public static async Task <Either <PowershellFailure, Option <TypedPsObject <VhdInfo> > > > GetVhdInfo(string path, IPowershellEngine engine)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return(Option <TypedPsObject <VhdInfo> > .None);
            }

            var res = await engine.GetObjectsAsync <VhdInfo>(new PsCommandBuilder().AddCommand("Get-VHD").AddArgument(path)).MapAsync(s => s.HeadOrNone());

            return(res);
        }
        private static Task <Either <PowershellFailure, Seq <TypedPsObject <VirtualMachineInfo> > > > GetVmInfo(string id,
                                                                                                                IPowershellEngine engine) =>

        Prelude.Cond <string>((c) => !string.IsNullOrWhiteSpace(c))(id).MatchAsync(
            None:  () => Seq <TypedPsObject <VirtualMachineInfo> > .Empty,
            Some: (s) => engine.GetObjectsAsync <VirtualMachineInfo>(PsCommandBuilder.Create()
                                                                     .AddCommand("get-vm").AddParameter("Id", s)
                                                                     //this a bit dangerous, because there may be other errors causing the
                                                                     //command to fail. However there seems to be no other way except parsing error response
                                                                     .AddParameter("ErrorAction", "SilentlyContinue")
                                                                     ));
Beispiel #8
0
        public static async Task Definition(
            IPowershellEngine engine,
            TypedPsObject <VirtualMachineInfo> vmInfo,
            MachineConfig vmConfig,
            Func <string, Task> reportProgress)
        {
            if (vmInfo.Value.Generation >= 2)
            {
                await engine.GetObjectsAsync <VMFirmwareInfo>(PsCommandBuilder.Create()
                                                              .AddCommand("Get-VMFirmware")
                                                              .AddParameter("VM", vmInfo.PsObject)).MapAsync(async(firmwareInfo) =>
                {
                    if (firmwareInfo.Head.Value.SecureBoot != OnOffState.Off)
                    {
                        await reportProgress($"Configure VM Firmware - Secure Boot: {OnOffState.Off}")
                        .ConfigureAwait(false);

                        await engine.RunAsync(PsCommandBuilder.Create()
                                              .AddCommand("Set-VMFirmware")
                                              .AddParameter("VM", vmInfo.PsObject)
                                              .AddParameter("EnableSecureBoot", OnOffState.Off)).ConfigureAwait(false);
                    }
                }).ConfigureAwait(false);
            }


            if (vmInfo.Value.ProcessorCount != vmConfig.VM.Cpu.Count)
            {
                await reportProgress($"Configure VM Processor: Count: {vmConfig.VM.Cpu.Count}").ConfigureAwait(false);

                await engine.RunAsync(PsCommandBuilder.Create()
                                      .AddCommand("Set-VMProcessor")
                                      .AddParameter("VM", vmInfo.PsObject)
                                      .AddParameter("Count", vmConfig.VM.Cpu.Count)).ConfigureAwait(false);
            }

            var memoryStartupBytes = vmConfig.VM.Memory.Startup * 1024L * 1024;

            if (vmInfo.Value.MemoryStartup != memoryStartupBytes)
            {
                await reportProgress($"Configure VM Memory: Startup: {vmConfig.VM.Memory.Startup} MB").ConfigureAwait(false);

                await engine.RunAsync(PsCommandBuilder.Create()
                                      .AddCommand("Set-VMMemory")
                                      .AddParameter("VM", vmInfo.PsObject)
                                      .AddParameter("StartupBytes", memoryStartupBytes)).ConfigureAwait(false);
            }
        }
Beispiel #9
0
        public static async Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > Firmware(TypedPsObject <VirtualMachineInfo> vmInfo,
                                                                                                             MachineConfig config, IPowershellEngine engine, Func <string, Task> reportProgress)
        {
            if (vmInfo.Value.Generation < 2)
            {
                return(vmInfo);
            }

            return(await engine.GetObjectsAsync <VMFirmwareInfo>(PsCommandBuilder.Create()
                                                                 .AddCommand("Get-VMFirmware")
                                                                 .AddParameter("VM", vmInfo.PsObject))
                   .BindAsync(firmwareInfoSeq =>
                              firmwareInfoSeq.HeadOrNone()
                              .Match <Either <PowershellFailure, TypedPsObject <VMFirmwareInfo> > >(
                                  None: () => new PowershellFailure {
                Message = "Failed to get VM Firmware"
            },
                                  Some: s => s
                                  ))
                   .BindAsync(async firmwareInfo =>
            {
                if (firmwareInfo.Value.SecureBoot != OnOffState.Off)
                {
                    await reportProgress($"Configure VM Firmware - Secure Boot: {OnOffState.Off}")
                    .ConfigureAwait(false);


                    var res = await engine.RunAsync(PsCommandBuilder.Create()
                                                    .AddCommand("Set-VMFirmware")
                                                    .AddParameter("VM", vmInfo.PsObject)
                                                    .AddParameter("EnableSecureBoot", OnOffState.Off)).MapAsync(
                        r => new TypedPsObject <VirtualMachineInfo>(vmInfo.PsObject)
                        ).ConfigureAwait(false);
                    return res;
                }

                return new TypedPsObject <VirtualMachineInfo>(vmInfo.PsObject);
            }
                              ).ConfigureAwait(false));
        }
Beispiel #10
0
        public static async Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > NetworkAdapter(
            VirtualMachineNetworkAdapterConfig networkAdapterConfig,
            IPowershellEngine engine,
            TypedPsObject <VirtualMachineInfo> vmInfo,
            MachineConfig machineConfig,
            Func <string, Task> reportProgress)
        {
            var optionalAdapter = await GetOrCreateInfoAsync(vmInfo,
                                                             i => i.NetworkAdapters,
                                                             adapter => networkAdapterConfig.Name.Equals(adapter.Name, StringComparison.OrdinalIgnoreCase),
                                                             async() =>
            {
                await reportProgress($"Add Network Adapter: {networkAdapterConfig.Name}").ConfigureAwait(false);
                return(await engine.GetObjectsAsync <VMNetworkAdapter>(PsCommandBuilder.Create()
                                                                       .AddCommand("Add-VmNetworkAdapter")
                                                                       .AddParameter("Passthru")
                                                                       .AddParameter("VM", vmInfo.PsObject)
                                                                       .AddParameter("Name", networkAdapterConfig.Name)
                                                                       .AddParameter("StaticMacAddress", UseOrGenerateMacAddress(networkAdapterConfig, vmInfo))
                                                                       .AddParameter("SwitchName", networkAdapterConfig.SwitchName)).ConfigureAwait(false));
            }).ConfigureAwait(false);

            return(optionalAdapter.Map(_ => vmInfo.Recreate()));

            //optionalAdapter.Map(async (adapter) =>
            //{
            //    if (!adapter.Value.Connected || adapter.Value.SwitchName != networkConfig.SwitchName)
            //    {
            //        await reportProgress($"Connect Network Adapter {adapter.Value.Name} to switch {networkConfig.SwitchName}").ConfigureAwait(false);
            //        await engine.RunAsync(
            //            PsCommandBuilder.Create().AddCommand("Connect-VmNetworkAdapter")
            //                .AddParameter("VMNetworkAdapter", adapter.PsObject)
            //                .AddParameter("SwitchName", networkConfig.SwitchName)).ConfigureAwait(false);

            //    }
            //});
            return(vmInfo.Recreate());
        }
 private Task <Either <PowershellFailure, Seq <TypedPsObject <MinimizedVMNetworkAdapter> > > > GetNetworkAdapters(TypedPsObject <MinimizedVirtualMachineInfo> vm)
 {
     return(_engine.GetObjectsAsync <MinimizedVMNetworkAdapter>(
                new PsCommandBuilder().AddCommand("Get-VMNetworkAdapter")
                .AddParameter("VM", vm.PsObject)));
 }
Beispiel #12
0
 public Task Handle(InventoryRequestedEvent message) =>
 _engine.GetObjectsAsync <MinimizedVirtualMachineInfo>(PsCommandBuilder.Create()
                                                       .AddCommand("get-vm"))
 .ToAsync()
 .IfRightAsync(vms => _bus.Send(VmsToInventory(vms)));
 private Task <Either <PowershellFailure, Option <TypedPsObject <VirtualMachineInfo> > > > GetVmInfo(Guid vmId,
                                                                                                     IPowershellEngine engine)
 {
     return(engine.GetObjectsAsync <VirtualMachineInfo>(CreateGetVMCommand(vmId)).MapAsync(seq => seq.HeadOrNone()));
 }
Beispiel #14
0
        public static async Task <Either <PowershellFailure, TypedPsObject <VirtualMachineInfo> > > VirtualDisk(
            VMDiskStorageSettings diskSettings,
            IPowershellEngine engine,
            TypedPsObject <VirtualMachineInfo> vmInfo,
            Seq <CurrentVMDiskStorageSettings> currentStorageSettings,
            Func <string, Task> reportProgress)
        {
            var currentSettings =
                currentStorageSettings.Find(x => diskSettings.Path.Equals(x.Path, StringComparison.OrdinalIgnoreCase) &&
                                            diskSettings.Name.Equals(x.Name, StringComparison.InvariantCultureIgnoreCase));
            var frozenOptional = currentSettings.Map(x => x.Frozen);

            if (frozenOptional.IsSome && frozenOptional.ValueUnsafe())
            {
                await reportProgress($"Skipping disk '{diskSettings.Name}': storage management is disabled for this disk.").ConfigureAwait(false);

                return(vmInfo);
            }



            return(await diskSettings.AttachPath.Map(async (vhdPath) =>
            {
                if (!File.Exists(vhdPath))
                {
                    await reportProgress($"Create VHD: {diskSettings.Name}").ConfigureAwait(false);

                    var createDiskResult = await diskSettings.ParentPath.Match(Some: parentPath =>
                    {
                        return engine.RunAsync(PsCommandBuilder.Create().Script(
                                                   $"New-VHD -Path \"{vhdPath}\" -ParentPath \"{parentPath}\" -Differencing"));
                    },
                                                                               None: () =>
                    {
                        return engine.RunAsync(PsCommandBuilder.Create().Script(
                                                   $"New-VHD -Path \"{vhdPath}\" -Dynamic -SizeBytes {diskSettings.SizeBytes}"));
                    });

                    if (createDiskResult.IsLeft)
                    {
                        return Prelude.Left(createDiskResult.LeftAsEnumerable().FirstOrDefault());
                    }
                }

                var sizeResult = await engine
                                 .GetObjectsAsync <VhdInfo>(new PsCommandBuilder().AddCommand("get-vhd").AddArgument(vhdPath))
                                 .BindAsync(x => x.HeadOrLeft(new PowershellFailure())).BindAsync(async(vhdInfo) =>
                {
                    if (vhdInfo.Value.Size != diskSettings.SizeBytes && diskSettings.SizeBytes > 0)
                    {
                        var gb = Math.Round(diskSettings.SizeBytes / 1024d / 1024 / 1024, 1);
                        await reportProgress(
                            $"Resizing disk {diskSettings.Name} to {gb} GB");
                        return await engine.RunAsync(PsCommandBuilder.Create().AddCommand("Resize-VHD")
                                                     .AddArgument(vhdPath)
                                                     .AddParameter("Size", diskSettings.SizeBytes));
                    }

                    return Unit.Default;
                });

                if (sizeResult.IsLeft)
                {
                    return Prelude.Left(sizeResult.LeftAsEnumerable().FirstOrDefault());
                }


                return await GetOrCreateInfoAsync(vmInfo,
                                                  i => i.HardDrives,
                                                  disk => currentSettings.Map(x => x.AttachedVMId) == disk.Id,
                                                  async() =>
                {
                    await reportProgress($"Attaching disk {diskSettings.Name} to controller: {diskSettings.ControllerNumber}, Location: {diskSettings.ControllerLocation}").ConfigureAwait(false);
                    return (await engine.GetObjectsAsync <HardDiskDriveInfo>(PsCommandBuilder.Create()
                                                                             .AddCommand("Add-VMHardDiskDrive")
                                                                             .AddParameter("VM", vmInfo.PsObject)
                                                                             .AddParameter("Path", vhdPath)
                                                                             .AddParameter("ControllerNumber", diskSettings.ControllerNumber)
                                                                             .AddParameter("ControllerLocation", diskSettings.ControllerLocation)
                                                                             .AddParameter("PassThru")
                                                                             ).ConfigureAwait(false));
                }).BindAsync(_ => vmInfo.RecreateOrReload(engine))


                .ConfigureAwait(false);
            }).IfNone(vmInfo.RecreateOrReload(engine)));
        }