Created
August 7, 2025 17:31
-
-
Save nanoDBA/f4171004c4e3ce5eab200a36f7f0f913 to your computer and use it in GitHub Desktop.
This function retrieves the volumes attached to the specified EC2 instances in the specified region. It returns a list of volume details including the instance ID, instance name, instance type, volume ID, device name, state, availability zone, volume type, IOPS, throughput, and size.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Get the volumes attached to the EC2 instances. | |
| .DESCRIPTION | |
| This function retrieves the volumes attached to the specified EC2 instances in the | |
| specified region. It returns a list of volume details including the instance ID, | |
| instance name, instance type, volume ID, device name, state, availability zone, | |
| volume type, IOPS, throughput, and size. | |
| .PARAMETER InstanceNames | |
| Specifies the names of the EC2 instances to retrieve the attached volumes for. | |
| Accepts multiple instance names if passed as an array. | |
| .PARAMETER InstanceId | |
| Specifies the ID of the EC2 instance to retrieve the attached volumes for. | |
| .PARAMETER Region | |
| Specifies the AWS region where the EC2 instances are located. | |
| .PARAMETER IncludeStateDetail | |
| Specifies whether to retrieve additional details about ongoing EBS volume | |
| modifications, such as the current state (e.g., 'modifying', 'optimizing') and | |
| progress percentage. | |
| .EXAMPLE | |
| Get-EC2VolumesAttached -InstanceNames Instance1 -Region us-west-2 -IncludeStateDetail | |
| Retrieves the volumes attached to the EC2 instance named "Instance1" in the | |
| "us-west-2" region, along with the detailed modification state of any EBS volumes | |
| that are currently being modified. | |
| .EXAMPLE | |
| PS C:\> Get-EC2VolumesAttached -InstanceNames Instance1 -Region us-west-2 | |
| Retrieves the volumes attached to the EC2 instance named "Instance1" in the | |
| "us-west-2" region. | |
| .EXAMPLE | |
| PS C:\> Get-EC2VolumesAttached -InstanceNames Instance1, Instance2 -Region us-east-1 | |
| Retrieves the volumes attached to the EC2 instances named "Instance1" and | |
| "Instance2" in the "us-east-1" region. | |
| .EXAMPLE | |
| PS C:\> Get-EC2VolumesAttached -InstanceId i-1234567890abcdef0 -Region us-west-2 | |
| Retrieves the volumes attached to the EC2 instance with the specified Instance ID | |
| in the "us-west-2" region. | |
| .EXAMPLE | |
| PS C:\> Get-EC2VolumesAttached -InstanceId i-1234567890abcdef0 -Region us-west-2 -IncludeStateDetail | |
| Retrieves the volumes attached to the EC2 instance with the specified Instance ID | |
| in the "us-west-2" region, including the detailed modification state of any EBS | |
| volumes being modified. | |
| .NOTES | |
| 2023-06-29 version originally by @nanoDBA, greatly enhanced by OpenAI's ChatGPT | |
| #> | |
| function Get-EC2VolumesAttached { | |
| [CmdletBinding()] | |
| param ( | |
| [Parameter(Mandatory=$true, ParameterSetName='ByName')] | |
| [string[]]$InstanceNames, # accept multiple instance names if passed | |
| [Parameter(Mandatory=$true, ParameterSetName='ById')] | |
| [string[]]$InstanceId, # accept multiple instance IDs if passed | |
| [Parameter(Mandatory=$true)] | |
| [string]$Region, | |
| [switch]$IncludeStateDetail # Switch to enable state detail fetching | |
| ) | |
| # Preload AWS SDK assemblies for EC2 to suppress unnecessary warnings in the output | |
| [System.Reflection.Assembly]::LoadWithPartialName("AWSSDK.EC2") | Out-Null | |
| # Initialize an array to store volume details from all instances | |
| $allVolumes = @() | |
| # Initialize an ordered hash table to track unique volume keys (VolumeId + InstanceId) | |
| $volumeKeys = [ordered]@{} | |
| $InstanceNames = $InstanceNames.ToLower() # convert array $InstanceNames to lowercase | |
| if ($PSCmdlet.ParameterSetName -eq 'ByName') { | |
| foreach ($InstanceName in $InstanceNames) { | |
| Write-Verbose "Checking instance with name: $InstanceName in region: $Region" | |
| $instProps = Get-EC2Instance -Filter @{name='tag:Name'; values=@($InstanceName)}, @{name='instance-state-name'; values='running'} -Region $Region | | |
| Select-Object -ExpandProperty Instances | | |
| Select-Object @{N='InstanceName'; E={$InstanceName}}, InstanceId, InstanceType | |
| if (-not $instProps) { | |
| Write-Verbose "Instance with name $InstanceName not found or not running in region $Region" | |
| continue | |
| } | |
| # Fetch volumes attached to these instances | |
| $allVolumes += Get-VolumesForInstances -Instances $instProps -Region $Region -VolumeKeys $volumeKeys -IncludeStateDetail:$IncludeStateDetail | |
| } | |
| } | |
| elseif ($PSCmdlet.ParameterSetName -eq 'ById') { | |
| Write-Verbose "Checking instance with ID: $InstanceId in region: $Region" | |
| $instProps = Get-EC2Instance -InstanceIds $InstanceId -Region $Region | | |
| Select-Object -ExpandProperty Instances | | |
| Select-Object @{N='InstanceName'; E={(Get-EC2Tag -ResourceId $_.InstanceId -Region $Region | Where-Object { $_.Key -eq 'Name' }).Value}}, InstanceId, InstanceType | |
| if ($instProps) { | |
| # Fetch volumes attached to these instances | |
| $allVolumes += Get-VolumesForInstances -Instances $instProps -Region $Region -VolumeKeys $volumeKeys -IncludeStateDetail:$IncludeStateDetail | |
| } else { | |
| Write-Verbose "Instance with ID $InstanceId not found in region $Region" | |
| } | |
| } | |
| # Remove any potential duplicates from $allVolumes | |
| $allVolumes = $allVolumes | Sort-Object -Property InstanceId, VolumeId -Unique | |
| # Return the complete list of volumes for all specified instances | |
| return $allVolumes | |
| } | |
| function Get-VolumesForInstances { | |
| [CmdletBinding()] | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [array]$Instances, | |
| [Parameter(Mandatory=$true)] | |
| [string]$Region, | |
| [Parameter(Mandatory=$true)] | |
| $VolumeKeys, | |
| [switch]$IncludeStateDetail # Switch to enable state detail fetching | |
| ) | |
| $volumes = @() | |
| foreach ($inst in $Instances) { | |
| Write-Verbose "Retrieving volumes for instance ID: $($inst.InstanceId) in region: $Region" | |
| $Volumes = Get-EC2Volume -Filter @{ Name = "attachment.instance-id"; Values = $inst.InstanceId } -Region $Region | | |
| Sort-Object {$_.Attachments.Device} | | |
| Select-Object -Property VolumeId, AvailabilityZone, VolumeType, Iops, Throughput, Size, | |
| @{N='Device'; E={$_.Attachments.Device}}, | |
| @{N='State'; E={$_.Attachments.State}}, | |
| @{N='InstanceId'; E={$_.Attachments.InstanceId}} | | |
| ForEach-Object { | |
| # Create a custom object with all necessary details including InstanceName and InstanceType | |
| $volObj = [PSCustomObject]@{ | |
| InstanceId = $inst.InstanceId | |
| InstanceName = $inst.InstanceName | |
| InstanceType = $inst.InstanceType | |
| VolumeId = $_.VolumeId | |
| Device = $_.Device | |
| State = $_.State | |
| AvailabilityZone = $_.AvailabilityZone | |
| VolumeType = $_.VolumeType | |
| Iops = $_.Iops | |
| Throughput = $_.Throughput | |
| Size = $_.Size | |
| } | |
| # Add detailed state if requested | |
| if ($IncludeStateDetail) { | |
| try { | |
| $volStateDetail = Get-EC2VolumeModification -VolumeId $volObj.VolumeId -Region $Region -ErrorAction Stop | |
| if ($volStateDetail) { | |
| $stateInfo = $volStateDetail | Select-Object -Property ModificationState, Progress | |
| $volObj | Add-Member -MemberType NoteProperty -Name 'StateDetail' -Value ("{0} ({1}%)" -f $stateInfo.ModificationState, $stateInfo.Progress) | |
| } else { | |
| $volObj | Add-Member -MemberType NoteProperty -Name 'StateDetail' -Value 'ready' | |
| } | |
| } catch { | |
| # Volume has no active modifications, which is normal | |
| $volObj | Add-Member -MemberType NoteProperty -Name 'StateDetail' -Value 'ready' | |
| } | |
| } | |
| $volObj | |
| } | |
| # Accumulate unique volumes from all instances | |
| foreach ($vol in $Volumes) { | |
| $key = "$($vol.VolumeId)-$($vol.InstanceId)" | |
| Write-Verbose "Processing volume with key: $key" | |
| if (-not $VolumeKeys.Contains($key)) { | |
| $VolumeKeys[$key] = $true | |
| Write-Verbose "Adding volume: $($vol.VolumeId) for instance: $($vol.InstanceId)" | |
| Write-Verbose "Volume details: $($vol | Out-String)" | |
| $volumes += $vol | |
| } else { | |
| Write-Verbose "Skipping duplicate volume: $($vol.VolumeId) for instance: $($vol.InstanceId)" | |
| } | |
| } | |
| } | |
| return $volumes | |
| } | |
| ############################################################################################################ | |
| # #2023-04-19 version | |
| # <# | |
| # .SYNOPSIS | |
| # Get the volumes attached to the EC2 instances. | |
| # .DESCRIPTION | |
| # This function retrieves the volumes attached to the specified EC2 instances in the specified region. | |
| # It returns a list of volume details including the instance ID, instance name, instance type, volume ID, device name, state, availability zone, volume type, IOPS, throughput, and size. | |
| # .PARAMETER InstanceNames | |
| # Specifies the names of the EC2 instances to retrieve the attached volumes for. Accepts multiple instance names if passed as an array. | |
| # .PARAMETER Region | |
| # Specifies the AWS region where the EC2 instances are located. | |
| # .EXAMPLE | |
| # Get-EC2VolumesAttached -InstanceNames Instance1 -Region us-west-2 | |
| # Retrieves the volumes attached to the EC2 instance named "Instance1" in the "us-west-2" region. | |
| # .EXAMPLE | |
| # Get-EC2VolumesAttached -InstanceNames Instance1, Instance2 -Region us-east-1 | |
| # Retrieves the volumes attached to the EC2 instances named "Instance1" and "Instance2" in the "us-east-1" region. | |
| # #> | |
| # function Get-EC2VolumesAttached { | |
| # param ( | |
| # [Parameter(Mandatory=$true)] | |
| # [string[]]$InstanceNames, # accept multiple instance names if passed | |
| # [Parameter(Mandatory=$true)] | |
| # [string]$Region | |
| # ) | |
| # $allVolumes = @() # Initialize an array to store volume details from all instances | |
| # foreach ($InstanceName in $InstanceNames) { | |
| # $instProps = Get-EC2Instance -Filter @{name='tag:Name'; values=@($InstanceName)}, @{name='instance-state-name'; values='running'} -Region $Region | | |
| # Select-Object -ExpandProperty Instances | | |
| # Select-Object @{N='InstanceName'; E={$InstanceName}}, InstanceId, InstanceType | |
| # if (-not $instProps) { | |
| # # Optionally handle the case where instance is not found or not running | |
| # continue | |
| # } | |
| # foreach ($inst in $instProps) { | |
| # $Volumes = Get-EC2Volume -Filter @{ Name = "attachment.instance-id"; Values = $inst.InstanceId } | | |
| # Sort-Object {$_.Attachments.Device} | | |
| # Select-Object -Property VolumeId, AvailabilityZone, VolumeType, Iops, Throughput, Size, | |
| # @{N='Device'; E={$_.Attachments.Device}}, | |
| # @{N='State'; E={$_.Attachments.State}}, | |
| # @{N='InstanceId'; E={$_.Attachments.InstanceId}} | | |
| # ForEach-Object { | |
| # [PSCustomObject]@{ | |
| # InstanceId = $inst.InstanceId | |
| # InstanceName = $inst.InstanceName | |
| # InstanceType = $inst.InstanceType | |
| # VolumeId = $_.VolumeId | |
| # Device = $_.Device | |
| # State = $_.State | |
| # AvailabilityZone = $_.AvailabilityZone | |
| # VolumeType = $_.VolumeType | |
| # Iops = $_.Iops | |
| # Throughput = $_.Throughput | |
| # Size = $_.Size | |
| # } | |
| # } | |
| # # Accumulate all volumes from all instances | |
| # $allVolumes += $Volumes | |
| # } | |
| # } | |
| # # Return the complete list of volumes for all specified instances | |
| # return $allVolumes | |
| # } | |
| ############################################################################################################ | |
| # <# 2023-11-17 version #> | |
| # # Get the volumes attached to the instance using the instance name passed in as a parameter to the Get-EC2VolumesAttached function | |
| # # Global variables are used to pass values between functions even though it's not best practice | |
| # function Get-EC2VolumesAttached { | |
| # param ( | |
| # [Parameter(Mandatory=$true)] | |
| # $InstanceName, | |
| # [Parameter(Mandatory=$true)] | |
| # $Region | |
| # ) | |
| # # Get the instance ID and assign it to the variable $InstanceId | |
| # $Vm = $InstanceName # assign the instance name to the variable $Vm | |
| # $instProps = (Get-EC2Instance -Filter @{name='tag:Name';values=$Vm}, @{name='instance-state-name';values='running'} -Region $Region).Instances | select @{N='InstanceName'; Expression={$Vm}}, InstanceId, InstanceType | |
| # # Get the instance ID and assign it to the variable $InstanceId | |
| # $InstanceId = $instProps.InstanceId | |
| # # If the instance ID is null, the instance was not found or is not currently in a running state | |
| # if ($instProps.InstanceId -eq $null) { | |
| # Write-Output "Instance $InstanceName not found or is not currently in a running state..." | |
| # } | |
| # else { | |
| # # Write the instance ID and instance name to the console | |
| # Write-Output "$InstanceId = $InstanceId | $InstanceName = $InstanceName" | |
| # # Get the volumes attached to the instance and sort them by device name such as /dev/sda1, /dev/xvdb, etc. | |
| # $Volumes = (Get-EC2Volume -Filter @{ Name = "attachment.instance-id"; Values = $InstanceId }) | sort-object -property {$_.Attachments.Device} | |
| # # Write the volumes attached to the instance to the console | |
| # foreach ($Vol in $Volumes) { | |
| # # Loop through the volumes attached to the instance and | |
| # # write the volume ID, instance ID, availability zone, device name, and size to the console | |
| # Write-Output "Volume $($Vol.VolumeId) is $($Vol.Attachments.State) to instance $($Vol.Attachments.InstanceId) in availability zone $($Vol.AvailabilityZone) Type: $($Vol.VolumeType) Iops: $($Vol.Iops) Throughput: $($Vol.Throughput) as device $($Vol.Attachments.Device) with size $($Vol.Size)" | |
| # } | |
| # } | |
| # } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment