Public/VM/Set-VergeVM.ps1
|
function Set-VergeVM { <# .SYNOPSIS Modifies the configuration of a VergeOS virtual machine. .DESCRIPTION Set-VergeVM modifies VM settings such as CPU cores, RAM, description, and other configuration options. Some changes may require a VM restart to take effect. .PARAMETER VM A VM object from Get-VergeVM. Accepts pipeline input. .PARAMETER Name The name of the VM to modify. .PARAMETER Key The key (ID) of the VM to modify. .PARAMETER NewName Rename the VM to this new name. .PARAMETER Description Set the VM description. .PARAMETER CPUCores Set the number of CPU cores (1-1024). .PARAMETER RAM Set the amount of RAM in MB (256-1048576). .PARAMETER OSFamily Set the operating system family: Linux, Windows, FreeBSD, Other. .PARAMETER GuestAgent Enable or disable QEMU Guest Agent support. .PARAMETER UEFI Enable or disable UEFI boot. .PARAMETER SecureBoot Enable or disable Secure Boot (requires UEFI). .PARAMETER Enabled Enable or disable the VM. .PARAMETER Console Set the console type: VNC, Spice, Serial, None. .PARAMETER Video Set the video card type: Standard, Cirrus, VMware, QXL, Virtio, None. .PARAMETER BootOrder Set the boot device order. .PARAMETER BootDelay Set the boot delay in seconds (0-60). .PARAMETER PassThru Return the modified VM object. .PARAMETER Server The VergeOS connection to use. Defaults to the current default connection. .EXAMPLE Set-VergeVM -Name "WebServer01" -CPUCores 8 -RAM 16384 Increases CPU to 8 cores and RAM to 16GB. .EXAMPLE Get-VergeVM -Name "WebServer01" | Set-VergeVM -Description "Production web server" Sets the VM description using pipeline input. .EXAMPLE Set-VergeVM -Name "OldName" -NewName "NewName" -PassThru Renames a VM and returns the updated object. .EXAMPLE Get-VergeVM -Name "Dev-*" | Set-VergeVM -GuestAgent $true Enables guest agent on all development VMs. .EXAMPLE Set-VergeVM -Name "WebServer01" -UEFI $true -SecureBoot $true Enables UEFI and Secure Boot (requires VM restart). .OUTPUTS None by default. Verge.VM when -PassThru is specified. .NOTES Some changes (CPU, RAM, UEFI) may require the VM to be powered off or restarted to take effect. The VM will show 'Restart Needed' status. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'ByName')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByVM')] [PSTypeName('Verge.VM')] [PSCustomObject]$VM, [Parameter(Mandatory, Position = 0, ParameterSetName = 'ByName')] [string]$Name, [Parameter(Mandatory, ParameterSetName = 'ByKey')] [int]$Key, [Parameter()] [ValidateLength(1, 128)] [string]$NewName, [Parameter()] [ValidateLength(0, 2048)] [string]$Description, [Parameter()] [ValidateRange(1, 1024)] [int]$CPUCores, [Parameter()] [ValidateRange(256, 1048576)] [int]$RAM, [Parameter()] [ValidateSet('Linux', 'Windows', 'FreeBSD', 'Other')] [string]$OSFamily, [Parameter()] [bool]$GuestAgent, [Parameter()] [bool]$UEFI, [Parameter()] [bool]$SecureBoot, [Parameter()] [bool]$Enabled, [Parameter()] [ValidateSet('VNC', 'Spice', 'Serial', 'None')] [string]$Console, [Parameter()] [ValidateSet('Standard', 'Cirrus', 'VMware', 'QXL', 'Virtio', 'None')] [string]$Video, [Parameter()] [ValidateSet('DiskCD', 'DiskCDNetwork', 'CDDisk', 'NetworkDisk', 'Network', 'Disk', 'CD')] [string]$BootOrder, [Parameter()] [ValidateRange(0, 60)] [int]$BootDelay, [Parameter()] [switch]$PassThru, [Parameter()] [object]$Server ) begin { # Resolve connection if (-not $Server) { $Server = $script:DefaultConnection } if (-not $Server) { throw [System.InvalidOperationException]::new( 'Not connected to VergeOS. Use Connect-VergeOS to establish a connection.' ) } # Map friendly names to API values $osFamilyMap = @{ 'Linux' = 'linux' 'Windows' = 'windows' 'FreeBSD' = 'freebsd' 'Other' = 'other' } $consoleMap = @{ 'VNC' = 'vnc' 'Spice' = 'spice' 'Serial' = 'serial' 'None' = 'none' } $videoMap = @{ 'Standard' = 'std' 'Cirrus' = 'cirrus' 'VMware' = 'vmware' 'QXL' = 'qxl' 'Virtio' = 'virtio' 'None' = 'none' } $bootOrderMap = @{ 'DiskCD' = 'cd' 'DiskCDNetwork' = 'cdn' 'CDDisk' = 'dc' 'NetworkDisk' = 'nc' 'Network' = 'n' 'Disk' = 'c' 'CD' = 'd' } } process { # Resolve VM based on parameter set $targetVM = switch ($PSCmdlet.ParameterSetName) { 'ByName' { Get-VergeVM -Name $Name -Server $Server | Select-Object -First 1 } 'ByKey' { Get-VergeVM -Key $Key -Server $Server } 'ByVM' { $VM } } if (-not $targetVM) { Write-Error -Message "VM not found" -ErrorId 'VMNotFound' return } # Check if VM is a snapshot if ($targetVM.IsSnapshot) { Write-Error -Message "Cannot modify '$($targetVM.Name)': VM is a snapshot" -ErrorId 'CannotModifySnapshot' return } # Build the update body with only specified parameters $body = @{} $changes = [System.Collections.Generic.List[string]]::new() if ($PSBoundParameters.ContainsKey('NewName')) { $body['name'] = $NewName $changes.Add("Name: $($targetVM.Name) -> $NewName") } if ($PSBoundParameters.ContainsKey('Description')) { $body['description'] = $Description $changes.Add("Description updated") } if ($PSBoundParameters.ContainsKey('CPUCores')) { $body['cpu_cores'] = $CPUCores $changes.Add("CPU: $($targetVM.CPUCores) -> $CPUCores") } if ($PSBoundParameters.ContainsKey('RAM')) { # Normalize RAM to 256 MB increments $normalizedRAM = [Math]::Ceiling($RAM / 256) * 256 $body['ram'] = $normalizedRAM $changes.Add("RAM: $($targetVM.RAM)MB -> ${normalizedRAM}MB") } if ($PSBoundParameters.ContainsKey('OSFamily')) { $body['os_family'] = $osFamilyMap[$OSFamily] $changes.Add("OS Family: $OSFamily") } if ($PSBoundParameters.ContainsKey('GuestAgent')) { $body['guest_agent'] = $GuestAgent $changes.Add("Guest Agent: $GuestAgent") } if ($PSBoundParameters.ContainsKey('UEFI')) { $body['uefi'] = $UEFI $changes.Add("UEFI: $UEFI") } if ($PSBoundParameters.ContainsKey('SecureBoot')) { $body['secure_boot'] = $SecureBoot $changes.Add("Secure Boot: $SecureBoot") if ($SecureBoot -and -not $UEFI -and -not $targetVM.UEFI) { Write-Warning "Secure Boot requires UEFI. Consider enabling UEFI as well." } } if ($PSBoundParameters.ContainsKey('Enabled')) { $body['enabled'] = $Enabled $changes.Add("Enabled: $Enabled") } if ($PSBoundParameters.ContainsKey('Console')) { $body['console'] = $consoleMap[$Console] $changes.Add("Console: $Console") } if ($PSBoundParameters.ContainsKey('Video')) { $body['video'] = $videoMap[$Video] $changes.Add("Video: $Video") } if ($PSBoundParameters.ContainsKey('BootOrder')) { $body['boot_order'] = $bootOrderMap[$BootOrder] $changes.Add("Boot Order: $BootOrder") } if ($PSBoundParameters.ContainsKey('BootDelay')) { $body['boot_delay'] = $BootDelay $changes.Add("Boot Delay: ${BootDelay}s") } # Check if there are any changes to make if ($body.Count -eq 0) { Write-Warning "No changes specified for VM '$($targetVM.Name)'" if ($PassThru) { Write-Output $targetVM } return } # Build change summary for confirmation $changeSummary = $changes -join ', ' if ($PSCmdlet.ShouldProcess($targetVM.Name, "Modify VM ($changeSummary)")) { try { Write-Verbose "Modifying VM '$($targetVM.Name)' (Key: $($targetVM.Key))" Write-Verbose "Changes: $changeSummary" $response = Invoke-VergeAPI -Method PUT -Endpoint "vms/$($targetVM.Key)" -Body $body -Connection $Server Write-Verbose "VM '$($targetVM.Name)' modified successfully" if ($PassThru) { # Return the updated VM Start-Sleep -Milliseconds 500 $vmKey = if ($PSBoundParameters.ContainsKey('NewName')) { # If renamed, we need to fetch by the new name or original key $targetVM.Key } else { $targetVM.Key } Get-VergeVM -Key $vmKey -Server $Server } } catch { Write-Error -Message "Failed to modify VM '$($targetVM.Name)': $($_.Exception.Message)" -ErrorId 'VMModifyFailed' } } } } |