Skip to content

Instantly share code, notes, and snippets.

@nanoDBA
Created August 7, 2025 17:31
Show Gist options
  • Select an option

  • Save nanoDBA/f4171004c4e3ce5eab200a36f7f0f913 to your computer and use it in GitHub Desktop.

Select an option

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.
<#
.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