При увеличении размера или удалении диска в VMWare для виртуальных машин с Windows, иногда сложно понять какой VMware virtual disk соответствует определенном диску в Windows ВМ. Если дисков не много и все они отличаются по размеру, найти нужный диск просто. Но что делать, если для ВМ создано несколько VMDK (или RDM) дисков одинакового размера, или для ВМ создано несколько виртуальных SCSI контроллеров? Как не ошибиться и выбрать именно тот диск, который требует расширить (или уменьшить ) администратор Windows.
В этой статье мы рассмотрим, как сопоставить диски Windows с виртуальными дисками (VMDK) на ВМ VMWare.
Проверяем номер SCSI устройства в Windows и VMWare
Откройте консоль управления дисками Disk Manager (diskmgmt.msc) в Windows (в нашем примере это Windows Server 2016). В списке дисков не отображается имя SCSI контроллера и номер SCSI устройства на нем. Чтобы определить номер SCSI устройства, щелкните по диску и выберите Properties . Как вы видите, на вкладке General в поле Location указано информация о порте устройства VMWare Virtual disk SCSI Disk Device .
- Location 160 = SCSI Bus Controller 0
- Target ID 1 = номер SCSI ID устройства 1
Объединяем полученные данные и получаем адрес диска SCSI(0:1).
Теперь откройте свойства виртуальной машины VMWare в vSphere Client. Найдите диск, у которого Virtual Device Node соответствует полученному ID. В нашем примере это SCSI(0:1) Hard Disk 2.
Если в виртуальной машине настроено множество виртуальных дисков с разными SCSI контроллерами (вы можете добавить в ВМ до 4 SCSI контроллеров по 16 дисков в каждом), найти номер SCSI устройства вручную довольно сложно. Кроме того, имейте в виду, что номера SCSI контроллеров в Windows и VMWare могут отличаться.
Как сопоставить диски Windows с VMDK файлами по UUID/SerialNumber через PowerShell?
Другой способ сопоставления виртуальных дисков VMWare с дисками внутри гостевой ВМ – сравнить их по уникальному идентификатору диска. Со стороны VMWare этот атрибут называется UUID (Unique ID), а в Windows – Serial Number . Рассмотрим, как получить значения UUID и SerialNumber виртуальных дисков через PowerShell.
disk.EnableUUID=TRUE
, это означает, что гостевая ОС должна видеть идентификаторы виртуальных дисков.Для получения информации о дисках в Windows вы можете использовать командлеты модуля Storage , или WMI запросы. Т.к. в нашем случае ещё остались ВМ с Windows Server 2008 R2, в которых отсутствует модуль Storage, мы будем использовать WMI.
Чтобы получить номер SCSI контроллера, номер SCSI устройства на нем, серийный номер виртуального диска (SerialNumber/UUID), размер и номер диска в Windows, выполите команду PowerShell:
$DiskInfo = foreach ($disk in Get-WmiObject Win32_DiskDrive) {_x000D_ [pscustomobject]@{_x000D_ "DeviceID"=$disk.DeviceID;_x000D_ "Caption"=$disk.Caption;_x000D_ "Capacity (GB)"=[math]::Round($disk.size / 1GB,0); _x000D_ "SerialNumber" =$disk.SerialNumber_x000D_ "SCSIControllerNum"=$disk.scsiport;_x000D_ "SCSIDeviceNum"=$disk.scsitargetid; _x000D_ }_x000D_}_x000D_$DiskInfo|ft
В нашем примере мы определили, что Windows видит три диска:
- PHYSICALDRIVE0: SCSI Port 0, SCSI Target 0, Serial 6000c2939b153417dedbdce371ed497b
- PHYSICALDRIVE1: SCSI Port 0, SCSI Target 1, Serial 6000c2950ee961954909259642bb03bf
- PHYSICALDRIVE1: SCSI Port 4, SCSI Target 10, Serial 6000c2995fc3c4728de8b0596bb02ce3
Теперь попробуем получить номера SCSI контроллеров и UUID дисков, которые указаны в настройках виртуальной машины VMware. Для получения параметров ВМ нужно воспользоваться PowerCLI .
Import-Module VMware.VimAutomation.Core -ErrorAction SilentlyContinue_x000D_connect-viserver vcenter1 _x000D__x000D_$vmName="msk-sql1"_x000D_$vmHardDisks = Get-VM -Name $vmName | Get-HardDisk _x000D_$vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View _x000D_$virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager _x000D__x000D_$vmresults = @() _x000D_foreach ($vmHardDisk in $vmHardDisks) _x000D_{ _x000D_ $string = $vmHardDisk.Filename_x000D_ $vmHardDiskUuid = ($vmHardDisk.ExtensionData.Backing.Uuid | ForEach-Object {$_.replace(' ','').replace('-','')})_x000D_ $vmresult = "" | Select-Object vmHardDiskDatastore,vmHardDiskVmdk,vmHardDiskName,vmHardDiskSize,vmHardDiskUuid_x000D_ $vmresult.vmHardDiskDatastore = $vmHardDisk.filename.split(']')[0].split('[')[1] _x000D_ $vmresult.vmHardDiskVmdk = $vmHardDisk.filename.split(']')[1].trim() _x000D_ $vmresult.vmHardDiskName = $vmHardDisk.Name_x000D_ $vmresult.vmHardDiskSize = $vmHardDisk.CapacityGB_x000D_ $vmresult.vmHardDiskUuid = $vmHardDiskUuid _x000D_ $vmresults += $vmresult _x000D_}_x000D_$vmresults | ft _x000D_
Данный скрипт подключится к серверу vCenter (или ESXi) и для указанной ВМ получит список дисков. После выполнения скрипта вы получите список виртуальных дисков для ВМ. Результат должен содержать имя DataStore, путь к vmdk файлу, номера диска, его размер и UUID.
Теперь по полученным UUID вы можете вручную сопоставить диски, которые видны в гостевой Windows с виртуальными дисками VMWare.
Если у вас есть права администратора в виртуальной машине, для которой нужно сопоставить диски Windows и vmdk файлы в VMWare, можно воспользоваться более простым в использовании PowerShell скриптом. Скрипт обращается к гостевой Windows по сети, собирает информацию о локальных дисках и показывает соответствие с дисками VMWare.
Полный код PowerShell скрипта:
Import-Module VMware.VimAutomation.Core -ErrorAction SilentlyContinue_x000D_connect-viserver vcenter1 _x000D_$vmName = "msk-sql1"_x000D_$WinHostName = "msk-sqlclu1.remontka.com"_x000D_#Получить список дисков виртуальной машины VMWare _x000D_$vmDisks = Get-VM -Name $vmName | Get-HardDisk _x000D_$vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View _x000D_$virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager _x000D_# Учетная запись и пароль администартора для доступа к гостевой ОС _x000D_$cred = if ($cred){$cred}else{Get-Credential} _x000D_# Получить список дисков и разделов Windows через WMI_x000D_$winDisk = Get-WmiObject -Class Win32_DiskDrive -ComputerName $WinHostName -Credential $cred_x000D_$diskToDriveVolume = Get-WmiObject Win32_DiskDrive -ComputerName $WinHostName -Credential $cred| % {_x000D_ $disk = $__x000D_ $partitions = "ASSOCIATORS OF " +_x000D_ "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +_x000D_ "WHERE AssocClass = Win32_DiskDriveToDiskPartition"_x000D_ Get-WmiObject -Query $partitions -ComputerName $WinHostName -Credential $cred| % {_x000D_ $partition = $__x000D_ $drives = "ASSOCIATORS OF " +_x000D_ "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +_x000D_ "WHERE AssocClass = Win32_LogicalDiskToPartition"_x000D_ Get-WmiObject -Query $drives -ComputerName $WinHostName -Credential $cred| % {_x000D_ New-Object -Type PSCustomObject -Property @{_x000D_ Disk = $disk.DeviceID_x000D_ DriveLetter = $_.DeviceID_x000D_ VolumeName = $_.VolumeName_x000D_ }_x000D_ }_x000D_ }_x000D_}_x000D_ #получить серийный номер диска _x000D_foreach ($disk in $winDisk) _x000D_{ _x000D_ $disk | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null _x000D_ $diskSerialNumber = $disk.SerialNumber _x000D_ if ($disk.Model -notmatch 'VMware Virtual disk SCSI Disk Device') _x000D_ { _x000D_ if ($diskSerialNumber -match '^S{12}$'){$diskSerialNumber = ($diskSerialNumber | foreach {[byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} } ) -join ''} _x000D_ $disk.AltSerialNumber = $diskSerialNumber _x000D_ } _x000D_} _x000D_#Перебор всех дисков ВМ, сопоставление с дисками Windows по SerialNumber / UUID _x000D_$diskMaps = @() _x000D_foreach ($vmDisk in $vmDisks) _x000D_{ _x000D_ $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')} _x000D_ $windowsDisk = $winDisk | where {$_.SerialNumber -eq $vmDiskUuid} _x000D_ if (-not $windowsDisk){$windowsDisk = $winDisk | where {$_.AltSerialNumber -eq $vmDisk.ScsiCanonicalName.substring(12,24)}} _x000D_ $curDiskMap = "" | select vmDiskDatastore, vmDiskVmdk, vmDiskName, windowsDiskIndex, vmDiskUuid, windowsDeviceID, drives, volumes _x000D_ $curDiskMap.vmDiskDatastore = $vmDisk.filename.split(']')[0].split('[')[1] _x000D_ $curDiskMap.vmDiskVmdk = $vmDisk.filename.split(']')[1].trim() _x000D_ $curDiskMap.vmDiskName = $vmDisk.Name _x000D_ $curDiskMap.windowsDiskIndex = if ($windowsDisk){$windowsDisk.Index}else{"FAILED TO MATCH"} _x000D_ $curDiskMap.vmDiskUuid = $vmDiskUuid _x000D_ $curDiskMap.windowsDeviceID = if ($windowsDisk){$windowsDisk.DeviceID}else{"FAILED TO MATCH"} _x000D_ $driveVolumes = $diskToDriveVolume | where {$_.Disk -eq $windowsDisk.DeviceID}_x000D_ $curDiskMap.drives = $driveVolumes.DriveLetter_x000D_ $curDiskMap.volumes = $driveVolumes.VolumeName_x000D_ $diskMaps += $curDiskMap_x000D_} _x000D_$diskMaps = $diskMaps | sort {[int]$_.vmDiskName.split(' ')[2]} _x000D_$diskMaps | ft_x000D_
Дополнительно возвращается информацию о буквах дисках и метках томов Windows.
Теперь вы можете без проблем разобраться какому виртуальному диску соответствует диск в Windows.