Public/Set-PVEVM.ps1
|
function Set-PVEVM { <# .SYNOPSIS Changes the configuration of QEMU virtual machines. .DESCRIPTION Sends the changes with POST /nodes/{node}/qemu/{vmid}/config, waits for the task, and writes each VM with its live status. On a running VM, PVE either applies a change at once or stores it as pending until the VM is next started, depending on the option and the VM's hotplug settings. After the change, a warning lists the options still pending on a running VM (read from GET .../pending). Only the options given are changed. -Parameter reaches any other option by its API name. .PARAMETER Name VM name(s). Wildcards allowed. .PARAMETER VMId VM ID(s). Binds from piped PVEPS.VM objects. .PARAMETER IncludeTemplate Let -Name match templates as well as VMs. .PARAMETER NewName New name for the VM. Only allowed when exactly one VM is targeted. .PARAMETER Cores Cores per socket. .PARAMETER Sockets CPU sockets. .PARAMETER MemoryGB Memory in GiB, sent to PVE in whole MiB. .PARAMETER CpuType Emulated CPU type, for example host or x86-64-v2-AES. .PARAMETER OSType Guest OS type (see New-PVEVM). .PARAMETER Description Description (notes). An empty string removes it. .PARAMETER Tags Tags, replacing the current ones. An empty array removes all tags. .PARAMETER StartOnBoot Whether the VM starts when the node boots. .PARAMETER Protection Whether the protection flag is set. While set, PVE refuses to delete the VM or its disks. .PARAMETER GuestAgent Whether the QEMU guest agent device is enabled. .PARAMETER Parameter Further options by their API names, for example @{ balloon = 2048 }. Applied last. .PARAMETER Delete Option names to remove from the configuration, so their PVE defaults apply, for example 'balloon'. .PARAMETER RunAsync Return the task(s) at once instead of waiting. .PARAMETER Server Connection(s) to use. Defaults to the default connection; binds from piped objects. .EXAMPLE Set-PVEVM -VMId 100 -Cores 4 -MemoryGB 8 .EXAMPLE Get-PVEVM -Name 'web*' | Set-PVEVM -Tags web, production -StartOnBoot $true .EXAMPLE Set-PVEVM web01 -NewName web01-old -Protection $false #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'ShouldProcess is called on this cmdlet through $PSCmdlet by Invoke-PVEGuestOperation.')] [CmdletBinding(DefaultParameterSetName = 'Id', SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType('PVEPS.VM', 'PVEPS.Task')] param( [Parameter(Mandatory, ParameterSetName = 'Name', Position = 0)] [SupportsWildcards()] [ValidateNotNullOrEmpty()] [string[]]$Name, [Parameter(Mandatory, ParameterSetName = 'Id', ValueFromPipelineByPropertyName)] [ValidateRange(100, 999999999)] [int[]]$VMId, [Parameter(ParameterSetName = 'Name')] [switch]$IncludeTemplate, [ValidateNotNullOrEmpty()] [string]$NewName, [ValidateRange(1, [int]::MaxValue)] [int]$Cores, [ValidateRange(1, [int]::MaxValue)] [int]$Sockets, [ValidateRange(0.015625, [double]::MaxValue)] [double]$MemoryGB, [ValidateNotNullOrEmpty()] [string]$CpuType, [ValidateSet('other', 'wxp', 'w2k', 'w2k3', 'w2k8', 'wvista', 'win7', 'win8', 'win10', 'win11', 'l24', 'l26', 'solaris')] [string]$OSType, [AllowEmptyString()] [string]$Description, [AllowEmptyCollection()] [string[]]$Tags, [bool]$StartOnBoot, [bool]$Protection, [bool]$GuestAgent, [hashtable]$Parameter, [ValidateNotNullOrEmpty()] [string[]]$Delete, [switch]$RunAsync, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Connection')] [object[]]$Server ) begin { $body = @{} $remove = [System.Collections.Generic.List[string]]::new() if ($NewName) { $body.name = $NewName } if ($PSBoundParameters.ContainsKey('Cores')) { $body.cores = $Cores } if ($PSBoundParameters.ContainsKey('Sockets')) { $body.sockets = $Sockets } if ($PSBoundParameters.ContainsKey('MemoryGB')) { $body.memory = ConvertTo-PVEMiB $MemoryGB } if ($CpuType) { $body.cpu = $CpuType } if ($OSType) { $body.ostype = $OSType } if ($PSBoundParameters.ContainsKey('Description')) { if ($Description) { $body.description = $Description } else { $remove.Add('description') } } if ($PSBoundParameters.ContainsKey('Tags')) { if ($Tags) { $body.tags = $Tags -join ';' } else { $remove.Add('tags') } } if ($PSBoundParameters.ContainsKey('StartOnBoot')) { $body.onboot = $StartOnBoot } if ($PSBoundParameters.ContainsKey('Protection')) { $body.protection = $Protection } if ($PSBoundParameters.ContainsKey('GuestAgent')) { $body.agent = [int]$GuestAgent } if ($Parameter) { foreach ($key in $Parameter.Keys) { $body[$key] = $Parameter[$key] } } foreach ($key in $Delete) { $remove.Add($key) } if ($remove.Count -gt 0) { $body.delete = $remove -join ',' } if ($body.Count -eq 0) { $PSCmdlet.ThrowTerminatingError((New-PVEArgumentError -Message 'No change given; specify at least one setting.' -Target $null)) } $targets = [System.Collections.Generic.List[psobject]]::new() } process { Add-PVEGuestTarget -Cmdlet $PSCmdlet -Target $targets -Server $Server -VMId $VMId -Name $Name } end { $guests = @(Resolve-PVEGuestTarget -Cmdlet $PSCmdlet -Type qemu -Target $targets -IncludeTemplate:$IncludeTemplate) if ($NewName -and $guests.Count -gt 1) { $PSCmdlet.ThrowTerminatingError((New-PVEArgumentError -Message "-NewName gives one name, but $($guests.Count) VMs are targeted; nothing was changed." -Target $guests)) } $action = 'Set {0}' -f (@($body.Keys | Sort-Object) -join ', ') foreach ($guest in @(Invoke-PVEGuestOperation -Cmdlet $PSCmdlet -Guest $guests -Description $action -Method POST -Suffix '/config' -Parameters $body -RunAsync:$RunAsync)) { if (-not $RunAsync) { try { Write-PVEPendingWarning -Guest $guest } catch { $PSCmdlet.WriteError($_) } } $guest } } } |