Public/Remove-DMPortFromPortGroup.ps1
|
<#
.SYNOPSIS Removes an OceanStor port from a port group. .DESCRIPTION Removes an existing front-end port or logical port association from an existing port group. The cmdlet resolves candidate ports by PortType, validates the selected port and group, checks current membership, then calls the OceanStor API. It supports -WhatIf and -Confirm. Accepts multiple ports from the pipeline by property name (all piped ports must share the same PortType). Each port is resolved and processed independently: a failure (e.g. an invalid/ambiguous name, or the port not being a member) is reported as a non-terminating error and does not stop the remaining ports from being processed. .PARAMETER WebSession Optional session object returned by Connect-deviceManager. When omitted, the module's cached $script:CurrentOceanstorSession session is used. .PARAMETER PortGroupName Name of the port group from which the port will be removed. .PARAMETER PortType Type of port to remove from the port group. Valid values are FibreChannel, Ethernet, and LogicalPort. .PARAMETER PortName Name of the port to remove from the port group. Valid values are resolved from the selected PortType. .PARAMETER VstoreId Optional vStore ID used to scope the association operation. .INPUTS System.Management.Automation.PSCustomObject .OUTPUTS System.Management.Automation.PSCustomObject Returns the OceanStor API error object. .EXAMPLE PS> Remove-DMPortFromPortGroup -PortGroupName 'fc-front-end' -PortType FibreChannel -PortName 'CTE0.A.IOM0.P0' -WhatIf Shows what would happen if the Fibre Channel port were removed from the fc-front-end port group. .NOTES Filename: Remove-DMPortFromPortGroup.ps1 #> function Remove-DMPortFromPortGroup { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(ValueFromPipelineByPropertyName = $true)] [pscustomobject]$WebSession, [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $session = if ($fakeBoundParameters.ContainsKey('WebSession')) { $fakeBoundParameters.WebSession } else { $script:CurrentOceanstorSession } (Get-DMPortGroup -WebSession $session).Name | Sort-Object -Unique | Where-Object { $_ -like "$wordToComplete*" } })] [string]$PortGroupName, [Parameter(Mandatory = $true, Position = 1)] [ValidateSet('FibreChannel', 'Ethernet', 'LogicalPort')] [string]$PortType, [Parameter(Mandatory = $true, Position = 2, ValueFromPipelineByPropertyName = $true)] [Alias('Name')] [ValidateNotNullOrEmpty()] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) if (-not $fakeBoundParameters.ContainsKey('PortType')) { return } $session = if ($fakeBoundParameters.ContainsKey('WebSession')) { $fakeBoundParameters.WebSession } else { $script:CurrentOceanstorSession } # Get-DMPortGroupCandidate is private and would not resolve here -- confirmed # empirically that an ArgumentCompleter scriptblock invoked by the real completion # engine can only reliably call already-public commands -- so its per-PortType # lookup is inlined directly instead of exposing it as a public command. $names = switch ($fakeBoundParameters.PortType) { 'FibreChannel' { (Get-DMPortFc -WebSession $session).Name } 'Ethernet' { (Get-DMPortETH -WebSession $session).Name } 'LogicalPort' { (Get-DMLif -WebSession $session).'LIF Name' } } $names | Sort-Object -Unique | Where-Object { $_ -like "$wordToComplete*" } })] [string]$PortName, [string]$VstoreId ) process { try { $session = if ($WebSession) { $WebSession } else { $script:CurrentOceanstorSession } $groups = @(Get-DMPortGroup -WebSession $session) $matchingGroups = @($groups | Where-Object Name -EQ $PortGroupName) if ($matchingGroups.Count -eq 0) { throw "Invalid PortGroupName. Valid values are: $($groups.Name -join ', ')" } if ($matchingGroups.Count -gt 1) { throw "PortGroupName is ambiguous because more than one port group is named '$PortGroupName'." } $group = $matchingGroups[0] $ports = @(Get-DMPortGroupCandidate -WebSession $session -PortType $PortType) $matchingPorts = @($ports | Where-Object Name -EQ $PortName) if ($matchingPorts.Count -eq 0) { throw "Invalid PortName for $PortType. Valid values are: $($ports.Name -join ', ')" } if ($matchingPorts.Count -gt 1) { throw "PortName is ambiguous because more than one $PortType port is named '$PortName'." } $port = $matchingPorts[0] $associationResource = "portgroup/associate?ASSOCIATEOBJTYPE=$($port.ObjectType)&ASSOCIATEOBJID=$($port.Id)" if ($VstoreId) { $associationResource += "&vstoreId=$VstoreId" } $associations = @(Invoke-DeviceManager -WebSession $session -Method 'GET' -Resource $associationResource | Select-DMResponseData) if (-not @($associations | Where-Object ID -EQ $group.Id)) { throw "Port '$PortName' is not a member of port group '$PortGroupName'." } $body = @{ ID = $group.Id ASSOCIATEOBJTYPE = $port.ObjectType ASSOCIATEOBJID = $port.Id } if ($VstoreId) { $body.vstoreId = $VstoreId } if ($PSCmdlet.ShouldProcess("$PortName <- $PortGroupName", 'Remove port from port group')) { $response = Invoke-DeviceManager -WebSession $session -Method 'DELETE' -Resource 'port/associate/portgroup' -BodyData $body $response = $response | Assert-DMApiSuccess return $response.error } } catch { $PSCmdlet.WriteError($_) } } } |