sorta kinda...

主にAWS関連ですが、これに限らずいろいろ勉強したことや思ったことを書いていきます。

Windows Server で EBS ボリューム ID とデバイス名とドライブレターの関連を確認したい

日々 Windows Server を触ることが増えてきました、那須です。

小さなことなんですが、わからなくて困ってて調べてたら AWS ドキュメントでまんま答えが見つかったので、忘れないように記事に書いておきます。

 

困っていたこと

ある Windows Server でディスクが 4 つついていて、そのうち 3 つが同じサイズでした。特定のボリュームだけスナップショットをとりたいけど、AWS コンソール上ではどのボリュームがその対象なのか判別できなくて困ってました。

文章だと難しいですね。OS 画面でいうとこんなディスク状況です。ディスク作成時にタグつけ忘れたらもうわかりません。 ドライブレターとサイズはわかりますが、AWS のボリューム ID はわかりません。
f:id:nasrinjp1:20180819160246p:plain

一方、AWS コンソール上ではデバイス名とボリューム ID とサイズはわかりますが、ドライブレターが見えません。
f:id:nasrinjp1:20180819165716p:plain

この状況で、例えば E ドライブだけスナップショットをとりたい場合、どのボリュームに対してスナップショットを作成すればいいか判別できるでしょうか?

 

見つけた AWS ドキュメント

まんま答えが書いてありました。
docs.aws.amazon.com

以下、スクリプトのコピペです。

function Get-EC2InstanceMetadata
{
    param([string]$Path)
    (Invoke-WebRequest -Uri "http://169.254.169.254/latest/$Path").Content 
}

function Convert-SCSITargetIdToDeviceName
{
    param([int]$SCSITargetId)
    If ($SCSITargetId -eq 0) {
        return "/dev/sda1"
    }
    $deviceName = "xvd"
    If ($SCSITargetId -gt 25) {
        $deviceName += [char](0x60 + [int]($SCSITargetId / 26))
    }
    $deviceName += [char](0x61 + $SCSITargetId % 26)
    return $deviceName
}

Try {
    $InstanceId = Get-EC2InstanceMetadata "meta-data/instance-id"
    $AZ = Get-EC2InstanceMetadata "meta-data/placement/availability-zone"
    $Region = $AZ.Remove($AZ.Length - 1)
    $BlockDeviceMappings = (Get-EC2Instance -Region $Region -Instance $InstanceId).Instances.BlockDeviceMappings
    $VirtualDeviceMap = @{}
    (Get-EC2InstanceMetadata "meta-data/block-device-mapping").Split("`n") | ForEach-Object {
        $VirtualDevice = $_
        $BlockDeviceName = Get-EC2InstanceMetadata "meta-data/block-device-mapping/$VirtualDevice"
        $VirtualDeviceMap[$BlockDeviceName] = $VirtualDevice
        $VirtualDeviceMap[$VirtualDevice] = $BlockDeviceName
    }
}
Catch {
    Write-Host "Could not access the AWS API, therefore, VolumeId is not available. 
  Verify that you provided your access keys." -ForegroundColor Yellow
}

Get-WmiObject -Class Win32_DiskDrive | ForEach-Object {
    $DiskDrive = $_
    $Volumes = Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='$($DiskDrive.DeviceID)'} WHERE AssocClass=Win32_DiskDriveToDiskPartition" | ForEach-Object {
        $DiskPartition = $_
        Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='$($DiskPartition.DeviceID)'} WHERE AssocClass=Win32_LogicalDiskToPartition"
    }
    If ($DiskDrive.PNPDeviceID -like "*PROD_PVDISK*") {
        $BlockDeviceName = Convert-SCSITargetIdToDeviceName($DiskDrive.SCSITargetId)
        $BlockDevice = $BlockDeviceMappings | Where-Object { $_.DeviceName -eq $BlockDeviceName }
        $VirtualDevice = If ($VirtualDeviceMap.ContainsKey($BlockDeviceName)) { $VirtualDeviceMap[$BlockDeviceName] } Else { $null }
    } ElseIf ($DiskDrive.PNPDeviceID -like "*PROD_AMAZON_EC2_NVME*") {
        $BlockDeviceName = Get-EC2InstanceMetadata "meta-data/block-device-mapping/ephemeral$($DiskDrive.SCSIPort - 2)"
        $BlockDevice = $null
        $VirtualDevice = If ($VirtualDeviceMap.ContainsKey($BlockDeviceName)) { $VirtualDeviceMap[$BlockDeviceName] } Else { $null }
    } Else {
        $BlockDeviceName = $null
        $BlockDevice = $null
        $VirtualDevice = $null
    }
    New-Object PSObject -Property @{
        Disk = $DiskDrive.Index;
        Partitions = $DiskDrive.Partitions;
        DriveLetter = If ($Volumes -eq $null) { "N/A" } Else { $Volumes.DeviceID };
        EbsVolumeId = If ($BlockDevice -eq $null) { "N/A" } Else { $BlockDevice.Ebs.VolumeId };
        Device = If ($BlockDeviceName -eq $null) { "N/A" } Else { $BlockDeviceName };
        VirtualDevice = If ($VirtualDevice -eq $null) { "N/A" } Else { $VirtualDevice };
        VolumeName = If ($Volumes -eq $null) { "N/A" } Else { $Volumes.VolumeName };
    }
} | Sort-Object Disk | Format-Table -AutoSize -Property Disk, Partitions, DriveLetter, EbsVolumeId, Device, VirtualDevice, VolumeName

 

t2.medium の Windows Server 2016 でテスト

AWS ドキュメントにある PowerShell スクリプトを使って、対象の Windows Server 上で ps1 ファイルを作成して実行しましょう。

f:id:nasrinjp1:20180819182300p:plain

PS C:\Users\Administrator\Desktop> .\vol-check.ps1

Disk Partitions DriveLetter EbsVolumeId           Device    VirtualDevice VolumeName
---- ---------- ----------- -----------           ------    ------------- ----------
   0          1 C:          vol-08daa03b6f1d83506 /dev/sda1 root
   1          1 D:          vol-0508d109e7ecc0d38 xvdb      ebs2          programs
   2          1 E:          vol-0180d15334525ff2d xvdc      ebs3          Data
   3          1 F:          vol-045116d3e27beddeb xvdd      ebs4          Logs

この通りあっさりでました。ドライブレター、ボリューム ID、デバイス名の関連が出てきましたね。 ちなみに、今回は下記の AMI から起動したインスタンスでテストしましたが、特に問題なく上記と同様の結果が出てきました。

  • Windows_Server-2016-English-Full-Base-2018.07.11 (ami-49096ba4)
  • Windows_Server-2016-Japanese-Full-Base-2018.03.24 (ami-07f2a061)
  • Windows_Server-2012-R2_RTM-English-64Bit-Base-2018.07.11 (ami-a73c5e4a)
  • Windows_Server-2012-R2_RTM-Japanese-64Bit-Base-2018.07.11 (ami-011270ec)

 

これでいつでも確認できますね

最初に EBS ボリュームにタグつけててもなんとなくあってるのかどうか不安になるのが人間です。 いつでもこの情報が見れるのは嬉しいですね。

 

Systems Manager で同じことやってみました

nasrinjp1.hatenablog.com