Public/New-PVEVMNetworkAdapter.ps1

function New-PVEVMNetworkAdapter {
  <#
  .SYNOPSIS
  Adds a network adapter to QEMU virtual machines.
  .DESCRIPTION
  Adds a netN entry at the lowest free index (or -Index) with POST /nodes/{node}/qemu/{vmid}/config, and
  writes the new PVEPS.VMNetworkAdapter object. PVE generates the MAC address unless -MacAddress is
  given. On a running VM, PVE hot-plugs the adapter if the VM's hotplug settings allow it; otherwise it
  is pending until the next start, and a warning says so.
  .PARAMETER VMId
  VM ID(s). Binds from piped PVEPS.VM objects.
  .PARAMETER VMName
  VM name(s). Wildcards allowed.
  .PARAMETER Bridge
  Bridge to connect the adapter to, for example vmbr0.
  .PARAMETER Model
  Adapter model. Defaults to virtio.
  .PARAMETER MacAddress
  MAC address, for example BC:24:11:12:34:56. Generated by PVE if omitted.
  .PARAMETER VlanTag
  VLAN tag for the adapter's traffic (1 to 4094).
  .PARAMETER Firewall
  Enable the PVE firewall on this adapter.
  .PARAMETER Disconnected
  Add the adapter with its link down (unplugged).
  .PARAMETER Mtu
  MTU (VirtIO only). 1 uses the bridge's MTU.
  .PARAMETER Queues
  Number of packet queues.
  .PARAMETER RateLimitMBps
  Rate limit in megabytes per second.
  .PARAMETER Index
  Index of the adapter, for example 1 for net1. Defaults to the lowest free index.
  .PARAMETER Parameter
  Further adapter options by their API names.
  .PARAMETER Server
  Connection(s) to use. Defaults to the default connection; binds from piped objects.
  .EXAMPLE
  New-PVEVMNetworkAdapter -VMId 100 -Bridge vmbr0 -VlanTag 20
  .EXAMPLE
  Get-PVEVM 'router*' | New-PVEVMNetworkAdapter -Bridge vmbr1 -Firewall
  #>

  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'ShouldProcess is called on this cmdlet through $PSCmdlet by Invoke-PVEGuestChange.')]
  [CmdletBinding(DefaultParameterSetName = 'Id', SupportsShouldProcess, ConfirmImpact = 'Medium')]
  [OutputType('PVEPS.VMNetworkAdapter')]
  param(
    [Parameter(Mandatory, ParameterSetName = 'Id', ValueFromPipelineByPropertyName)]
    [ValidateRange(100, 999999999)]
    [int[]]$VMId,

    [Parameter(Mandatory, ParameterSetName = 'Name', Position = 0)]
    [SupportsWildcards()]
    [ValidateNotNullOrEmpty()]
    [string[]]$VMName,

    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [string]$Bridge,

    [ValidateSet('e1000', 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em', 'e1000e', 'i82551', 'i82557b', 'i82559er', 'ne2k_isa', 'ne2k_pci', 'pcnet', 'rtl8139', 'virtio', 'vmxnet3')]
    [string]$Model = 'virtio',

    [ValidatePattern('^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$')]
    [string]$MacAddress,

    [ValidateRange(1, 4094)]
    [int]$VlanTag,

    [switch]$Firewall,

    [switch]$Disconnected,

    [ValidateRange(1, 65520)]
    [int]$Mtu,

    [ValidateRange(0, 64)]
    [int]$Queues,

    [ValidateRange(0, [double]::MaxValue)]
    [double]$RateLimitMBps,

    [ValidateRange(0, [int]::MaxValue)]
    [int]$Index,

    [hashtable]$Parameter,

    [Parameter(ValueFromPipelineByPropertyName)]
    [Alias('Connection')]
    [object[]]$Server
  )

  begin {
    $option = [ordered]@{ model = $Model; macaddr = $(if ($MacAddress) { $MacAddress.ToUpperInvariant() } else { $null }); bridge = $Bridge }
    if ($PSBoundParameters.ContainsKey('VlanTag')) { $option.tag = $VlanTag }
    if ($Firewall) { $option.firewall = 1 }
    if ($Disconnected) { $option.link_down = 1 }
    if ($PSBoundParameters.ContainsKey('Mtu')) { $option.mtu = $Mtu }
    if ($PSBoundParameters.ContainsKey('Queues')) { $option.queues = $Queues }
    if ($PSBoundParameters.ContainsKey('RateLimitMBps')) { $option.rate = $RateLimitMBps.ToString([cultureinfo]::InvariantCulture) }
    if ($Parameter) {
      foreach ($key in $Parameter.Keys) {
        $option[$key] = $Parameter[$key]
      }
    }
    $value = ConvertTo-PVENetworkOptionString -Option $option
    $targets = [System.Collections.Generic.List[psobject]]::new()
  }

  process {
    Add-PVEGuestTarget -Cmdlet $PSCmdlet -Target $targets -Server $Server -VMId $VMId -Name $VMName
  }

  end {
    foreach ($guest in @(Resolve-PVEGuestTarget -Cmdlet $PSCmdlet -Type qemu -Target $targets)) {
      $slot = if ($PSBoundParameters.ContainsKey('Index')) { $Index } else { -1 }
      Add-PVEGuestDevice -Cmdlet $PSCmdlet -Guest $guest -Prefix net -Index $slot -Value $value -Kind VMNetworkAdapter -Description "Add network adapter {key} on $Bridge"
    }
  }
}