Public/OSDCloud/OSDCloudVM.ps1
|
function Get-OSDCloudVMDefaults { <# .SYNOPSIS Gets the OSDCloudVM Module defaults from $Global:OSDModuleResource.NewOSDCloudVM .DESCRIPTION Gets the OSDCloudVM Module defaults from $Global:OSDModuleResource.NewOSDCloudVM .EXAMPLE Get-OSDCloudVMDefaults .NOTES Author: David Segura - Recast Software 2026-07-09 - Standardized comment-based help metadata and links. .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> [CmdletBinding()] param () # OSDCloudVM Module Defaults $Results = [ordered]@{ CheckpointVM = [System.Boolean]$Global:OSDModuleResource.NewOSDCloudVM.CheckpointVM Generation = [System.Int16]$Global:OSDModuleResource.NewOSDCloudVM.Generation MemoryStartupGB = [System.Int64]$Global:OSDModuleResource.NewOSDCloudVM.MemoryStartupGB NamePrefix = [System.String]$Global:OSDModuleResource.NewOSDCloudVM.NamePrefix ProcessorCount = [System.Int64]$Global:OSDModuleResource.NewOSDCloudVM.ProcessorCount StartVM = [System.Boolean]$Global:OSDModuleResource.NewOSDCloudVM.StartVM SwitchName = [System.String]$Global:OSDModuleResource.NewOSDCloudVM.SwitchName VHDSizeGB = [System.Int64]$Global:OSDModuleResource.NewOSDCloudVM.VHDSizeGB } $Results } function Get-OSDCloudVMSettings { <# .SYNOPSIS Gets information returned by Get-OSDCloudVMSettings. .DESCRIPTION Provides the implementation for Get-OSDCloudVMSettings. .EXAMPLE Get-OSDCloudVMSettings Runs Get-OSDCloudVMSettings with common parameters. .NOTES Author: David Segura - Recast Software 2026-07-09 - Updated comment-based help .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> [CmdletBinding()] param () # OSDCloudVM Module Defaults $OSDCloudVMSettings = Get-OSDCloudVMDefaults # Create Template Logs Directory $TemplateLogs = "$env:ProgramData\OSDCloud\Logs" if (-NOT (Test-Path $TemplateLogs)) { $null = New-Item -Path $TemplateLogs -ItemType Directory -Force | Out-Null } # Import Template Defaults $TemplateConfigurationJson = "$env:ProgramData\OSDCloud\Logs\NewOSDCloudVM.json" if (Test-Path $TemplateConfigurationJson) { Write-Host -ForegroundColor DarkGray "Importing OSDCloudVM Template settings at $TemplateConfigurationJson" $TemplateConfiguration = Get-Content -Path $TemplateConfigurationJson -Raw | ConvertFrom-Json -ErrorAction "Stop" | ConvertTo-Hashtable if ($TemplateConfiguration) { foreach ($Key in $TemplateConfiguration.Keys) { $OSDCloudVMSettings.$Key = $TemplateConfiguration.$Key } } } # Import Workspace Defaults $WorkspaceConfigurationJson = Join-Path (Get-OSDCloudWorkspace) 'Logs\NewOSDCloudVM.json' if (Test-Path $WorkspaceConfigurationJson) { Write-Host -ForegroundColor DarkGray "Importing OSDCloudVM Workspace settings at $WorkspaceConfigurationJson" $WorkspaceConfiguration = Get-Content -Path $WorkspaceConfigurationJson -Raw | ConvertFrom-Json -ErrorAction "Stop" | ConvertTo-Hashtable if ($WorkspaceConfiguration) { foreach ($Key in $WorkspaceConfiguration.Keys) { $OSDCloudVMSettings.$Key = $WorkspaceConfiguration.$Key } } } # Display the updated settings Return $OSDCloudVMSettings } function New-OSDCloudVM { <# .SYNOPSIS Creates resources by using New-OSDCloudVM. .DESCRIPTION Provides the implementation for New-OSDCloudVM. .PARAMETER CheckpointVM Specifies the value for CheckpointVM. .PARAMETER Generation Specifies the value for Generation. .PARAMETER MemoryStartupGB Specifies the value for MemoryStartupGB. .PARAMETER NamePrefix Specifies the value for NamePrefix. .PARAMETER ProcessorCount Specifies the value for ProcessorCount. .PARAMETER StartVM Specifies the value for StartVM. .PARAMETER SwitchName Specifies the value for SwitchName. .PARAMETER VHDSizeGB Specifies the value for VHDSizeGB. .EXAMPLE New-OSDCloudVM -CheckpointVM <CheckpointVM> -Generation <Generation> Runs New-OSDCloudVM with common parameters. .NOTES Author: David Segura - Recast Software 2026-07-09 - Updated comment-based help .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> [CmdletBinding()] param ( [System.Boolean] $CheckpointVM, [ValidateSet('1','2')] [System.UInt16] $Generation, [ValidateRange(2, 64)] [System.UInt16] $MemoryStartupGB, [System.String] $NamePrefix, [ValidateRange(2, 64)] [System.UInt16] $ProcessorCount, [System.Boolean] $StartVM, [System.String] $SwitchName, [ValidateRange(8, 128)] [System.UInt16] $VHDSizeGB ) # OSDCloudVM $Global:NewOSDCloudVM = Get-OSDCloudVMSettings # Update Configuration from Parameters if ($PSBoundParameters.ContainsKey('CheckpointVM')) {$Global:NewOSDCloudVM.CheckpointVM = $CheckpointVM} if ($PSBoundParameters.ContainsKey('Generation')) {$Global:NewOSDCloudVM.Generation = $Generation} if ($PSBoundParameters.ContainsKey('MemoryStartupGB')) {$Global:NewOSDCloudVM.MemoryStartupGB = $MemoryStartupGB} if ($PSBoundParameters.ContainsKey('NamePrefix')) {$Global:NewOSDCloudVM.NamePrefix = $NamePrefix} if ($PSBoundParameters.ContainsKey('ProcessorCount')) {$Global:NewOSDCloudVM.ProcessorCount = $ProcessorCount} if ($PSBoundParameters.ContainsKey('StartVM')) {$Global:NewOSDCloudVM.StartVM = $StartVM} if ($PSBoundParameters.ContainsKey('SwitchName')) {$Global:NewOSDCloudVM.SwitchName = $SwitchName} if ($PSBoundParameters.ContainsKey('VHDSizeGB')) {$Global:NewOSDCloudVM.VHDSizeGB = $VHDSizeGB} # Validate SwitchName if ($Global:NewOSDCloudVM.SwitchName) { $ValidateSwitch = Get-VMSwitch -Name $Global:NewOSDCloudVM.SwitchName -ErrorAction SilentlyContinue if (-not ($ValidateSwitch)) { Write-Warning "SwitchName value '$($Global:NewOSDCloudVM.SwitchName)' is not valid and will be set to Not connected." $Global:NewOSDCloudVM.SwitchName = $null } } # Export the updated configuration $WorkspaceConfigurationJson = Join-Path (Get-OSDCloudWorkspace) 'Logs\NewOSDCloudVM.json' Write-Host -ForegroundColor DarkGray "Exporting updated configuration to $WorkspaceConfigurationJson" $Global:NewOSDCloudVM | ConvertTo-Json -Depth 10 | Out-File -FilePath $WorkspaceConfigurationJson -Force if ($Reset) { $Global:OSDCloudVM = $null $Global:OSDCloudVM = [ordered]@{ CheckpointVM = $NewOSDCloudVM.CheckpointVM Generation = $NewOSDCloudVM.Generation MemoryStartupBytes = ($NewOSDCloudVM.MemoryStartupGB * 1GB) MemoryStartupGB = $NewOSDCloudVM.MemoryStartupGB NamePrefix = $NewOSDCloudVM.NamePrefix ProcessorCount = $NewOSDCloudVM.ProcessorCount StartVM = $NewOSDCloudVM.StartVM SwitchName = $NewOSDCloudVM.SwitchName VHDSizeGB = [System.Int64]$Global:NewOSDCloudVM.VHDSizeGB } # Display the current configuration Write-Output $Global:OSDCloudVM } else { # Get Hyper-V Defaults #$VMManagementService = Get-WmiObject -Namespace root\virtualization\v2 Msvm_VirtualSystemManagementService $VMManagementServiceSettingData = Get-WmiObject -Namespace root\virtualization\v2 Msvm_VirtualSystemManagementServiceSettingData # Set VM Name $VmName = "$($NewOSDCloudVM.NamePrefix)$((Get-Date).ToString('yyMMddHHmmss'))" if (($Global:OSDKBootMedia) -and (Test-Path $($Global:OSDKBootMedia.BootMediaPath) -ErrorAction SilentlyContinue)) { $DvdDrivePath = Join-Path $($Global:OSDKBootMedia.BootMediaPath) 'OSDKBoot_NoPrompt.iso' } elseif (Test-Path (Join-Path $(Get-OSDCloudWorkspace) 'OSDeploy_NoPrompt.iso')) { $DvdDrivePath = Join-Path $(Get-OSDCloudWorkspace) 'OSDeploy_NoPrompt.iso' } elseif (Test-Path (Join-Path $(Get-OSDCloudWorkspace) 'OSDCloud_NoPrompt.iso')) { $DvdDrivePath = Join-Path $(Get-OSDCloudWorkspace) 'OSDCloud_NoPrompt.iso' } elseif (Test-Path (Join-Path $(Get-OSDCloudWorkspace) 'OSDKBoot_NoPrompt.iso')) { $DvdDrivePath = Join-Path $(Get-OSDCloudWorkspace) 'OSDKBoot_NoPrompt.iso' } elseif (Test-Path (Join-Path $(Get-OSDCloudWorkspace) 'BootMedia_NoPrompt.iso')) { $DvdDrivePath = Join-Path $(Get-OSDCloudWorkspace) 'BootMedia_NoPrompt.iso' } elseif (Test-Path (Join-Path $(Get-OSDCloudWorkspace) 'WinRE_NoPrompt.iso')) { $DvdDrivePath = Join-Path $(Get-OSDCloudWorkspace) 'WinRE_NoPrompt.iso' } # Build Final Configuration $Global:OSDCloudVM = $null $Global:OSDCloudVM = [ordered]@{ CheckpointVM = $NewOSDCloudVM.CheckpointVM DvdDrivePath = $DvdDrivePath Generation = $NewOSDCloudVM.Generation MemoryStartupBytes = ($NewOSDCloudVM.MemoryStartupGB * 1GB) MemoryStartupGB = $NewOSDCloudVM.MemoryStartupGB Name = $VmName NamePrefix = $NewOSDCloudVM.NamePrefix ProcessorCount = $NewOSDCloudVM.ProcessorCount StartVM = $NewOSDCloudVM.StartVM SwitchName = $NewOSDCloudVM.SwitchName VHDPath = [System.String](Join-Path $VMManagementServiceSettingData.DefaultVirtualHardDiskPath "$VmName.vhdx") VHDSizeBytes = ($NewOSDCloudVM.VHDSizeGB * 1GB) VHDSizeGB = [System.Int64]$Global:NewOSDCloudVM.VHDSizeGB } # Display the current configuration Write-Output $Global:OSDCloudVM # Create VM VHD if ($OSDCloudVM.SwitchName) { $vm = New-VM -Name $OSDCloudVM.Name -Generation $OSDCloudVM.Generation -MemoryStartupBytes $OSDCloudVM.MemoryStartupBytes -NewVHDPath $OSDCloudVM.VHDPath -NewVHDSizeBytes $OSDCloudVM.VHDSizeBytes -SwitchName $OSDCloudVM.SwitchName -Verbose -ErrorAction Stop } else { $vm = New-VM -Name $OSDCloudVM.Name -Generation $OSDCloudVM.Generation -MemoryStartupBytes $OSDCloudVM.MemoryStartupBytes -NewVHDPath $OSDCloudVM.VHDPath -NewVHDSizeBytes $OSDCloudVM.VHDSizeBytes -Verbose -ErrorAction Stop } # Create DVD $OSDCloudVM.DvdDrive = $vm | Add-VMDvdDrive -Path $OSDCloudVM.DvdDrivePath -Passthru -Verbose $OSDCloudVM.HardDiskDrive = $vm | Get-VMHardDiskDrive $OSDCloudVM.NetworkAdapter = $vm | Get-VMNetworkAdapter if ($OSDCloudVM.Generation -eq 2) { # First Boot Device $vm | Set-VMFirmware -FirstBootDevice $OSDCloudVM.DvdDrive # Firmware #$vm | Set-VMFirmware -BootOrder $OSDCloudVM.DvdDrive, $vmHardDiskDrive, $vmNetworkAdapter -Verbose # Security $vm | Set-VMFirmware -EnableSecureBoot On -Verbose if ((Get-TPM).TpmPresent -eq $true -and (Get-TPM).TpmReady -eq $true) { $vm | Set-VMSecurity -VirtualizationBasedSecurityOptOut:$false -Verbose $vm | Set-VMKeyProtector -NewLocalKeyProtector -Verbose $vm | Enable-VMTPM -Verbose } } # Memory $vm | Set-VMMemory -DynamicMemoryEnabled $false -Verbose # Processor $vm | Set-VMProcessor -Count $OSDCloudVM.ProcessorCount -Verbose # Integration Services # Thanks Andreas Landry $IntegrationService = Get-VMIntegrationService -VMName $vm.Name | Where-Object { $_ -match "Microsoft:[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}\\6C09BB55-D683-4DA0-8931-C9BF705F6480" } $vm | Get-VMIntegrationService -Name $IntegrationService.Name | Enable-VMIntegrationService -Verbose # Checkpoints Start Stop $vm | Set-VM -AutomaticCheckpointsEnabled $false -AutomaticStartAction Nothing -AutomaticStartDelay 3 -AutomaticStopAction Shutdown -Verbose #Export Final Configuration $Global:OSDCloudVM.VM = $vm Write-Verbose "Exporting current configuration to $env:Temp\OSDCloudVM.json" $Global:OSDCloudVM | ConvertTo-Json -Depth 2 | Out-File -FilePath "$env:TEMP\OSDCloudVM.json" -Force if ($Global:OSDCloudVM.CheckpointVM -eq $true) { $vm | Checkpoint-VM -SnapshotName 'New-VM' -Verbose } if ($Global:OSDCloudVM.StartVM -eq $true) { vmconnect.exe $env:ComputerName $OSDCloudVM.Name Start-Sleep -Seconds 3 $vm | Start-VM -Verbose } } } Register-ArgumentCompleter -CommandName New-OSDCloudVM -ParameterName 'SwitchName' -ScriptBlock {Get-VMSwitch | Select-Object -ExpandProperty Name | ForEach-Object {if ($_.Contains(' ')) {"'$_'"} else {$_}}} function Reset-OSDCloudVMSettings { <# .SYNOPSIS Resets configuration by using Reset-OSDCloudVMSettings. .DESCRIPTION Provides the implementation for Reset-OSDCloudVMSettings. .EXAMPLE Reset-OSDCloudVMSettings Runs Reset-OSDCloudVMSettings with common parameters. .NOTES Author: David Segura - Recast Software 2026-07-09 - Updated comment-based help .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> [CmdletBinding()] param () $TemplateConfigurationJson = "$env:ProgramData\OSDCloud\Logs\NewOSDCloudVM.json" if (Test-Path $TemplateConfigurationJson) { Write-Warning "Removing OSDCloudVM Template configuration at $TemplateConfigurationJson" Remove-Item -Path $TemplateConfigurationJson -Force -ErrorAction SilentlyContinue | Out-Null } $WorkspaceConfigurationJson = Join-Path (Get-OSDCloudWorkspace) 'Logs\NewOSDCloudVM.json' if (Test-Path $WorkspaceConfigurationJson) { Write-Warning "Removing OSDCloudVM Workspace configuration at $WorkspaceConfigurationJson" Remove-Item -Path $WorkspaceConfigurationJson -Force -ErrorAction SilentlyContinue | Out-Null } Get-OSDCloudVMSettings } function Set-OSDCloudVMSettings { <# .SYNOPSIS Sets configuration values by using Set-OSDCloudVMSettings. .DESCRIPTION Provides the implementation for Set-OSDCloudVMSettings. .PARAMETER CheckpointVM Specifies the value for CheckpointVM. .PARAMETER Generation Specifies the value for Generation. .PARAMETER MemoryStartupGB Specifies the value for MemoryStartupGB. .PARAMETER NamePrefix Specifies the value for NamePrefix. .PARAMETER ProcessorCount Specifies the value for ProcessorCount. .PARAMETER StartVM Specifies the value for StartVM. .PARAMETER SwitchName Specifies the value for SwitchName. .PARAMETER VHDSizeGB Specifies the value for VHDSizeGB. .EXAMPLE Set-OSDCloudVMSettings -CheckpointVM <CheckpointVM> -Generation <Generation> Runs Set-OSDCloudVMSettings with common parameters. .NOTES Author: David Segura - Recast Software 2026-07-09 - Updated comment-based help .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> [CmdletBinding()] param ( [System.Boolean] $CheckpointVM, [ValidateSet('1','2')] [System.UInt16] $Generation, [ValidateRange(2, 64)] [System.UInt16] $MemoryStartupGB, [System.String] $NamePrefix, [ValidateRange(2, 64)] [System.UInt16] $ProcessorCount, [System.Boolean] $StartVM, [System.String] $SwitchName, [ValidateRange(8, 128)] [System.UInt16] $VHDSizeGB ) # OSDCloudVM Module Defaults $OSDCloudVMSettings = Get-OSDCloudVMDefaults # Create Template Logs Directory $TemplateLogs = "$env:ProgramData\OSDCloud\Logs" if (-NOT (Test-Path $TemplateLogs)) { $null = New-Item -Path $TemplateLogs -ItemType Directory -Force | Out-Null } # Import Template Defaults $TemplateConfigurationJson = "$env:ProgramData\OSDCloud\Logs\NewOSDCloudVM.json" if (Test-Path $TemplateConfigurationJson) { Write-Host -ForegroundColor DarkGray "Importing OSDCloudVM Template settings at $TemplateConfigurationJson" $TemplateConfiguration = Get-Content -Path $TemplateConfigurationJson -Raw | ConvertFrom-Json -ErrorAction "Stop" | ConvertTo-Hashtable if ($TemplateConfiguration) { foreach ($Key in $TemplateConfiguration.Keys) { $OSDCloudVMSettings.$Key = $TemplateConfiguration.$Key } } } # Update Configuration from Parameters if ($PSBoundParameters.ContainsKey('CheckpointVM')) {$OSDCloudVMSettings.CheckpointVM = $CheckpointVM} if ($PSBoundParameters.ContainsKey('Generation')) {$OSDCloudVMSettings.Generation = $Generation} if ($PSBoundParameters.ContainsKey('MemoryStartupGB')) {$OSDCloudVMSettings.MemoryStartupGB = $MemoryStartupGB} if ($PSBoundParameters.ContainsKey('NamePrefix')) {$OSDCloudVMSettings.NamePrefix = $NamePrefix} if ($PSBoundParameters.ContainsKey('ProcessorCount')) {$OSDCloudVMSettings.ProcessorCount = $ProcessorCount} if ($PSBoundParameters.ContainsKey('StartVM')) {$OSDCloudVMSettings.StartVM = $StartVM} if ($PSBoundParameters.ContainsKey('SwitchName')) {$OSDCloudVMSettings.SwitchName = $SwitchName} if ($PSBoundParameters.ContainsKey('VHDSizeGB')) {$OSDCloudVMSettings.VHDSizeGB = $VHDSizeGB} # Validate SwitchName if ($OSDCloudVMSettings.SwitchName) { $ValidateSwitch = Get-VMSwitch -Name $OSDCloudVMSettings.SwitchName -ErrorAction SilentlyContinue if (-not ($ValidateSwitch)) { Write-Warning "SwitchName value '$($OSDCloudVMSettings.SwitchName)' is not valid and will be set to Not connected." $OSDCloudVMSettings.SwitchName = $null } } # Export the updated configuration Write-Host -ForegroundColor Cyan "Exporting updated configuration to $TemplateConfigurationJson" $OSDCloudVMSettings | ConvertTo-Json -Depth 10 | Out-File -FilePath $TemplateConfigurationJson -Force # Display the updated settings Return $OSDCloudVMSettings } Register-ArgumentCompleter -CommandName Set-OSDCloudVMSettings -ParameterName 'SwitchName' -ScriptBlock {Get-VMSwitch | Select-Object -ExpandProperty Name | ForEach-Object {if ($_.Contains(' ')) {"'$_'"} else {$_}}} |