Private/Invoke-PVEGuestClone.ps1
|
function Invoke-PVEGuestClone { <# .SYNOPSIS Shared engine for Copy-PVEVM and Copy-PVEContainer. .DESCRIPTION Resolves the collected targets to exactly one source guest (templates included, by ID or name), picks the new ID (Get-PVENewVMId), asks ShouldProcess on the calling cmdlet, then POSTs /nodes/{node}/{type}/{vmid}/clone. Complete-PVEOperation waits for the task and writes the new guest, or the task with -RunAsync. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'Calls ShouldProcess on the calling public cmdlet, passed as -Cmdlet, so its -WhatIf and -Confirm apply.')] [CmdletBinding()] [OutputType([psobject])] param( [Parameter(Mandatory)] [System.Management.Automation.PSCmdlet]$Cmdlet, [Parameter(Mandatory)] [ValidateSet('qemu', 'lxc')] [string]$Type, [Parameter(Mandatory)] [AllowEmptyCollection()] [System.Collections.Generic.List[psobject]]$Target, [Parameter(Mandatory)] [string]$NewName, [int]$NewVMId, # Clone options other than newid and the name, by their API names. [Parameter(Mandatory)] [hashtable]$Parameters, [switch]$RunAsync ) $kind = if ($Type -eq 'qemu') { 'VM' } else { 'Container' } $sources = @(Resolve-PVEGuestTarget -Cmdlet $Cmdlet -Type $Type -Target $Target -IncludeTemplate) if ($sources.Count -eq 0) { return } if ($sources.Count -gt 1) { $Cmdlet.WriteError((New-PVEArgumentError -Message ('The source matched {0} guests ({1}); clone one source at a time.' -f $sources.Count, (@($sources | ForEach-Object { $_.VMId }) -join ', ')) -Target $sources)) return } $source = $sources[0] try { $id = Get-PVENewVMId -Connection $source.Connection -VMId $NewVMId } catch { $Cmdlet.WriteError($_) return } $body = @{ newid = $id } + $Parameters $body[$(if ($Type -eq 'lxc') { 'hostname' } else { 'name' })] = $NewName $mode = if ($Parameters.ContainsKey('full')) { 'full clone' } elseif ($source.IsTemplate) { 'linked clone' } else { 'full clone' } $action = 'Clone ({0}) to {1} {2} ({3})' -f $mode, $kind, $id, $NewName if (-not $Cmdlet.ShouldProcess((Get-PVEGuestLabel -Guest $source), $action)) { return } $path = Format-PVEPath '/nodes/{node}/{type}/{vmid}/clone' @{ node = $source.Node; type = $Type; vmid = $source.VMId } try { $upid = Invoke-PVERequest -Connection $source.Connection -Method POST -Path $path -Parameters $body } catch { $Cmdlet.WriteError($_) return } Write-Verbose "$action`: task $upid" $operations = [System.Collections.Generic.List[psobject]]::new() $pool = if ($Parameters.ContainsKey('pool')) { [string]$Parameters.pool } else { $null } $operations.Add([pscustomobject]@{ Upid = [string]$upid; Connection = $source.Connection; Guest = $null; Type = $Type; Node = $source.Node; VMId = $id; Pool = $pool }) Complete-PVEOperation -Cmdlet $Cmdlet -Operation $operations -RunAsync:$RunAsync } |