Private/Resolve-PVEGuestTarget.ps1
|
function Resolve-PVEGuestTarget { <# .SYNOPSIS Resolves the -VMId / -Name targets collected by Add-PVEGuestTarget into guest objects. .DESCRIPTION Reads /cluster/resources once per connection. Unknown IDs and exact names, and guests of the other type, are reported as errors on the calling cmdlet (with a hint naming the right cmdlets). Each guest is written once, in the order first named, even if several targets match it. An ID names exactly one guest, so it matches templates too. A name matches templates only with -IncludeTemplate, so a wildcard such as 'web*' does not sweep up templates by accident. With -PassTarget, writes one { Guest; Target } pair per target and matching guest instead, without removing duplicates, so device cmdlets can tell which devices were asked for on which guest. Pairs for the same guest share the same guest object. #> [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, [switch]$IncludeTemplate, [switch]$PassTarget ) $kind = if ($Type -eq 'qemu') { 'VM' } else { 'Container' } $otherHint = if ($Type -eq 'qemu') { 'It is a container; use the *-PVEContainer cmdlets.' } else { 'It is a VM; use the *-PVEVM cmdlets.' } $templateHint = 'It is a template; add -IncludeTemplate.' $seen = [System.Collections.Generic.HashSet[string]]::new() foreach ($group in ($Target | Group-Object -Property { $_.Connection.Id })) { $connection = $group.Group[0].Connection try { $guests = @(Invoke-PVERequest -Connection $connection -Path '/cluster/resources' -Parameters @{ type = 'vm' } | ConvertTo-PVEGuest -Connection $connection) } catch { $Cmdlet.WriteError($_) continue } foreach ($item in $group.Group) { if ($null -ne $item.VMId) { $found = @($guests | Where-Object { $_.VMId -eq $item.VMId }) if ($found.Count -eq 0) { Write-PVENotFound -Cmdlet $Cmdlet -Kind "$kind with ID" -Filter $item.VMId -Found @() -Server $connection.Server } elseif ($found[0].Type -ne $Type) { Write-PVENotFound -Cmdlet $Cmdlet -Kind "$kind with ID" -Filter $item.VMId -Found @() -Server $connection.Server -HintValue $item.VMId -Hint $otherHint $found = @() } } else { $named = @($guests | Where-Object { $_.Type -eq $Type -and $_.Name -like $item.Name } | Sort-Object -Property VMId) $found = @($named | Where-Object { $IncludeTemplate -or -not $_.IsTemplate }) if ($found.Count -eq 0) { if ($named.Count -gt 0) { Write-PVENotFound -Cmdlet $Cmdlet -Kind "$kind with name" -Filter $item.Name -Found @() -Server $connection.Server -HintValue $item.Name -Hint $templateHint } else { $otherNames = @($guests | Where-Object { $_.Type -ne $Type } | ForEach-Object { $_.Name }) Write-PVENotFound -Cmdlet $Cmdlet -Kind "$kind with name" -Filter $item.Name -Found @() -Server $connection.Server -HintValue $otherNames -Hint $otherHint } } } foreach ($guest in $found) { if ($PassTarget) { [pscustomobject]@{ Guest = $guest; Target = $item } continue } if ($seen.Add(('{0}/{1}' -f $connection.Id, $guest.VMId))) { $guest } } } } } |