The below function returns BlockDeviceName
and EBS VolumeID
for a given drive letter when executed within the context of an EC2 host. It handles for drives that span multiple disks, but not for disks spanning multiple EBS volumes.
function Get-EbsDeets {
[cmdletbinding()]Param(
[string[]]$DriveLetter
)
# $wmiVol = Get-WmiObject Win32_Volume | Where DriveLetter -eq "$DriveLetter`:"
$wmiLd = Get-WmiObject Win32_LogicalDisk | Where {($_.DeviceID).Trim(':') -in $DriveLetter}
$wmiLd | ForEach-Object {
$Letter = $_.DeviceID
$wmiLd2p = Get-WmiObject Win32_LogicalDiskToPartition | Where Dependent -in $_.__PATH
$wmiDd2p = Get-WmiObject Win32_DiskDriveToDiskPartition | Where Dependent -in $wmiLd2p.Antecedent
$wmiDsk = Get-WmiObject Win32_DiskDrive | Where __PATH -in $wmiDd2p.Antecedent
$wmiDsk | ForEach-Object {
$EstimatedVolumeId = $_.SerialNumber.Insert(3,'-')
$DeviceName = (ec2WinVolMap $_.SCSIBus -target $_.SCSITargetId -lun $_.SCSILogicalUnit).DeviceName
$VolumeType = (ec2WinVolMap $_.SCSIBus -target $_.SCSITargetId -lun $_.SCSILogicalUnit).VolumeType
$SizeGb = [Math]::Round(($_.Size / 1gb),2)
[PSCustomObject]@{
DriveLetter = $Letter
DiskNumber = $_.DeviceId
DeviceName = $DeviceName
VolumeType = $VolumeType
VolumeId = $EstimatedVolumeId
SizeGb = $SizeGb
}
}
}
}
Function ec2WinVolMap {
[cmdletBinding()]Param(
$bus
,$target
,$lun
)
# https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-volumes.html#windows-volume-mapping
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html
$Lookup = @"
Bus,Target,LUN,DeviceName,VolumeType
0,0,0,/dev/sda1,ebs
0,1,0,xvdb, ebs
0,2,0,xvdc, ebs
0,3,0,xvdd, ebs
0,4,0,xvde, ebs
0,5,0,xvdf, ebs
0,6,0,xvdg, ebs
0,7,0,xvdh, ebs
0,8,0,xvdi, ebs
0,9,0,xvdj, ebs
0,10,0,xvdk,ebs
0,11,0,xvdl,ebs
0,12,0,xvdm,ebs
0,13,0,xvdn,ebs
0,14,0,xvdo,ebs
0,15,0,xvdp,ebs
0,16,0,xvdq,ebs
0,17,0,xvdr,ebs
0,18,0,xvds,ebs
0,19,0,xvdt,ebs
0,20,0,xvdu,ebs
0,21,0,xvdv,ebs
0,22,0,xvdw,ebs
0,23,0,xvdx,ebs
0,24,0,xvdy,ebs
0,25,0,xvdz,ebs
0,78,0,xvdca,instance-store
0,79,0,xvdcb,instance-store
0,80,0,xvdcc,instance-store
0,81,0,xvdcd,instance-store
0,82,0,xvdce,instance-store
0,83,0,xvdcf,instance-store
0,84,0,xvdcg,instance-store
0,85,0,xvdch,instance-store
0,86,0,xvdci,instance-store
0,87,0,xvdcj,instance-store
0,88,0,xvdck,instance-store
0,89,0,xvdcl,instance-store
"@ | ConvertFrom-Csv
$DeviceName = ($Lookup | Where-Object {
$_.Bus -eq $bus -and `
$_.Target -eq $target -and `
$_.LUN -eq $lun
}).DeviceName
$VolumeType = ($Lookup | Where-Object {
$_.Bus -eq $bus -and `
$_.Target -eq $target -and `
$_.LUN -eq $lun
}).VolumeType
[PSCustomObject]@{
DeviceName = $DeviceName
VolumeType = $VolumeType
}
}
Explanation
Given the above limitation, you can estimate the EBS VolumeID
for (the first volume in) a given disk by inspecting the SerialNumber
attribute on Win32_DiskDrive
. As noted in @bjoster
's answer, you can also retrieve the bus, target, and lun values necessary to look up the BlockDeviceName
based on the table in the previously linked AWS documentation.
Frustratingly though, this doesn't easily map back to the actual drive letter or name which you're likely to receive in an actual user complaint. To associate these attributes (found on the Win32_LogicalDisk
collection in my case), you can daisy chain back through the antecedent/dependent mappings on the Win32_LogicalDiskToPartition
and Win32_DiskDriveToDiskPartition
collections.
When cobbling this together, I noted that on my installation Win32_DiskDriveToDiskPartition
maps 1:1 for disks. While Win32_LogicalDiskToPartition
does match the number of EBS volumes (in the case of multiple volumes per disk), I haven't bothered just yet to figure out how to associate the bus, target, and lun needed to get the BlockDeviceName
for the non-primary underlying volume(s) when they exist. If these are retrieved but for some reason the EBS VolumeID
isn't immediately known for the non-primary volumes, there may be some thought of calling the AWSPowerShell function in the following way
$bdn = 'xvdg'
# assuming you've tagged your instance with the hostname
$ec2 = Get-EC2Instance -Filter @{Name='tag:Name';Values='EC2-Server-1'}
($ec2.Instances.BlockDeviceMappings | Where DeviceName -eq $bdn).Ebs