Public/New-PVEContainerVolume.ps1

function New-PVEContainerVolume {
  <#
  .SYNOPSIS
  Adds a mount point to LXC containers: a new volume, or a bind mount of a host directory.
  .DESCRIPTION
  Adds an mpN entry at the lowest free index (or -Index) with PUT /nodes/{node}/lxc/{vmid}/config, and
  writes the new PVEPS.ContainerVolume object. -SizeGB with -Storage creates a new volume; -HostPath
  bind-mounts a directory of the host. The API documentation restricts mount points that are not storage
  volumes (bind mounts) to root@pam.

  On a running container the mount point can be pending until the next start, and a warning says so.
  .PARAMETER VMId
  Container ID(s). Binds from piped PVEPS.Container objects.
  .PARAMETER VMName
  Container name(s). Wildcards allowed.
  .PARAMETER Path
  Mount path inside the container, for example /srv/data.
  .PARAMETER SizeGB
  Size of the new volume in GiB. Needs -Storage.
  .PARAMETER Storage
  Storage for the new volume.
  .PARAMETER HostPath
  Host directory to bind-mount instead of creating a volume.
  .PARAMETER ReadOnly
  Mount read-only.
  .PARAMETER Backup
  Include the mount point in backups. The API documentation says this applies only to volume mount
  points.
  .PARAMETER Index
  Index of the mount point, for example 1 for mp1. Defaults to the lowest free index.
  .PARAMETER Parameter
  Further mount point options by their API names, for example @{ mountoptions = 'noatime' }.
  .PARAMETER Server
  Connection(s) to use. Defaults to the default connection; binds from piped objects.
  .EXAMPLE
  New-PVEContainerVolume -VMId 200 -Path /srv/data -SizeGB 20 -Storage local-lvm -Backup
  .EXAMPLE
  New-PVEContainerVolume -VMId 200 -Path /mnt/media -HostPath /tank/media -ReadOnly
  #>

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

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

    [Parameter(Mandatory)]
    [ValidatePattern('^/')]
    [string]$Path,

    [ValidateRange(1, [int]::MaxValue)]
    [int]$SizeGB,

    [ValidateNotNullOrEmpty()]
    [string]$Storage,

    [ValidatePattern('^/')]
    [string]$HostPath,

    [switch]$ReadOnly,

    [switch]$Backup,

    [ValidateRange(0, 255)]
    [int]$Index,

    [hashtable]$Parameter,

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

  begin {
    if ($HostPath -and ($SizeGB -or $Storage)) {
      $PSCmdlet.ThrowTerminatingError((New-PVEArgumentError -Message 'Give either -HostPath, or -SizeGB with -Storage, not both.' -Target $HostPath))
    }
    if (-not $HostPath -and -not ($SizeGB -and $Storage)) {
      $PSCmdlet.ThrowTerminatingError((New-PVEArgumentError -Message 'Give -SizeGB with -Storage for a new volume, or -HostPath for a bind mount.' -Target $null))
    }
    $option = [ordered]@{ volume = if ($HostPath) { $HostPath } else { '{0}:{1}' -f $Storage, $SizeGB }; mp = $Path }
    if ($ReadOnly) { $option.ro = 1 }
    if ($Backup) { $option.backup = 1 }
    if ($Parameter) {
      foreach ($key in $Parameter.Keys) {
        $option[$key] = $Parameter[$key]
      }
    }
    $value = ConvertTo-PVEPropertyString -Option $option -DefaultKey volume
    $what = if ($HostPath) { "bind mount of $HostPath" } else { "$SizeGB GiB on $Storage" }
    $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 lxc -Target $targets)) {
      $slot = if ($PSBoundParameters.ContainsKey('Index')) { $Index } else { -1 }
      Add-PVEGuestDevice -Cmdlet $PSCmdlet -Guest $guest -Prefix mp -Index $slot -Count 256 -Value $value -Kind ContainerVolume -Description "Add mount point {key} at $Path ($what)"
    }
  }
}