将Windows磁盘与VMWare VMDK文件匹配
扩大VMWare虚拟机的磁盘大小或者删除磁盘时,有时很难理解哪个VMware虚拟磁盘与特定的Windows VM磁盘匹配。如果磁盘很少,并且它们的大小不同,则很容易找到所需的磁盘。但是,如果为虚拟机创建了多个相同大小的VMDK(或者RDM)磁盘或者多个虚拟SCSI控制器,该怎么办?如何避免错误并选择Windows管理员要求我们扩展(或者收缩)的磁盘?
在本文中,很好地了解了如何在VMWare VM上匹配Windows磁盘和虚拟磁盘(VMDK)。
如何在Windows和VMWare中获取SCSI设备号?
打开磁盘管理控制台(
diskmgmt.msc
)(在我们的示例中为Windows Server 2015)。 SCSI控制器名称和SCSI设备号未显示在磁盘列表中。要获取SCSI设备号,请右键单击磁盘,然后选择"属性"。如我们所见,有关VMWare虚拟磁盘SCSI磁盘设备的设备端口的信息显示在"常规"选项卡的"位置"字段中。
- 位置160 = SCSI总线控制器0
- 目标ID1 =设备SCSI ID为1
加入我们所看到的数据,并获得SCSI磁盘地址:SCSI(0:1)。
然后在VMWare vSphere Client中打开虚拟机属性。查找具有与我们获得的ID相同的虚拟设备节点号的磁盘。在我们的示例中,它是" SCSI(0:1)"硬盘2.
如果在虚拟机上配置了具有不同SCSI控制器的多个虚拟磁盘(我们最多可以将4个SCSI控制器(每个磁盘有16个磁盘)添加到虚拟机),那么手动查找SCSI设备号将是非常困难的。另外请注意,Windows和VMWare中的SCSI控制器编号可能会有所不同。
如何使用PowerShell通过UUID /序列号将Windows磁盘与VMDK匹配?
将VMWare虚拟磁盘映射到来宾VM中的磁盘的另一种方法是比较其唯一的磁盘ID。在VMWare中,此属性称为" UUID"(唯一ID),在Windows中,此属性称为"序列号"。让我们看看如何使用PowerShell获取虚拟磁盘的UUID和序列号。
默认情况下,所有VMWare VM都有磁盘
EnableUUID=TRUE
参数已启用。这意味着来宾操作系统必须看到虚拟磁盘ID。
要获取有关Windows中磁盘的信息,可以使用存储模块cmdlet或者WMI查询。由于我们仍然有一些运行Windows Server 2008 R2的VM没有存储模块,因此我们将使用WMI。
要获取SCSI控制器号,其上的SCSI设备号,虚拟磁盘的序列号(SerialNumber/UUID),Windows中的磁盘大小和磁盘号,请运行以下PowerShell命令:
$DiskInfo = foreach ($disk in Get-WmiObject Win32_DiskDrive) {
[pscustomobject]@{
"DeviceID"=$disk.DeviceID;
"Caption"=$disk.Caption;
"Capacity (GB)"=[math]::Round($disk.size/1GB,0);
"SerialNumber" =$disk.SerialNumber
"SCSIControllerNum"=$disk.scsiport;
"SCSIDeviceNum"=$disk.scsitargetid;
}
}
$DiskInfo|ft
在我们的示例中,Windows检测到了三个磁盘:
- PHYSICALDRIVE0:SCSI端口0,SCSI目标0,串行6000c2939b157427dadbace321ed4973
- PHYSICALDRIVE1:SCSI端口0,SCSI目标1,串行6000c2950ee961954909938642bb03b4
- PHYSICALDRIVE1:SCSI端口4,SCSI目标10,序列号6000c2995fc3c4928d6650596bb02cef
然后,让我们尝试获取在VMWare虚拟机的设置中指定的磁盘的SCSI控制器编号和UUID。要查看VM设置,请使用PowerCLI控制台。
Import-Module VMware.VimAutomation.Core -ErrorAction SilentlyContinue
connect-viserver ber-vmware1
$vmName="ber-man01"
$vmHardDisks = Get-VM -Name $vmName | Get-HardDisk
$vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View
$virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager
$vmresults = @()
foreach ($vmHardDisk in $vmHardDisks)
{
$string = $vmHardDisk.Filename
$vmHardDiskUuid = ($vmHardDisk.ExtensionData.Backing.Uuid | ForEach-Object {$_.replace(' ','').replace('-','')})
$vmresult = "" | Select-Object vmHardDiskDatastore,vmHardDiskVmdk,vmHardDiskName,vmHardDiskSize,vmHardDiskUuid
$vmresult.vmHardDiskDatastore = $vmHardDisk.filename.split(']')[0].split('[')[1]
$vmresult.vmHardDiskVmdk = $vmHardDisk.filename.split(']')[1].trim()
$vmresult.vmHardDiskName = $vmHardDisk.Name
$vmresult.vmHardDiskSize = $vmHardDisk.CapacityGB
$vmresult.vmHardDiskUuid = $vmHardDiskUuid
$vmresults += $vmresult
}
$vmresults | ft
该脚本将连接到vCenter(或者ESXi)服务器,并获取指定VM的磁盘列表。结果必须包含数据存储名称,VMDK文件路径,磁盘号,磁盘大小和UUID。
然后,我们可以通过其UUID手动将在来宾Windows操作系统中看到的磁盘与VMWare虚拟磁盘进行匹配。
如果我们在VM的来宾OS中具有管理员权限,则可以使用更方便的PowerShell脚本来匹配Windows磁盘和VMWare VMDK文件。该脚本通过网络连接来宾Windows操作系统,收集有关其本地磁盘的信息,并将其与VMWare VMDK匹配。
这是PowerShell脚本的完整代码:
Import-Module VMware.VimAutomation.Core -ErrorAction SilentlyContinue
connect-viserver ber-vmware1
$vmName = "ber-man01"
$WinHostName = "ber-mansrv01.theitroad.local"
#Get the list of disks of a VMWare virtual machine
$vmDisks = Get-VM -Name $vmName | Get-HardDisk
$vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View
$virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager
# Enter the administrator credentials to access the guest Windows
$cred = if ($cred){$cred}else{Get-Credential}
# Getting the list of Windows disks and partitions using WMI
$winDisk = Get-WmiObject -Class Win32_DiskDrive -ComputerName $WinHostName -Credential $cred
$diskToDriveVolume = Get-WmiObject Win32_DiskDrive -ComputerName $WinHostName -Credential $cred| % {
$disk = $_
$partitions = "ASSOCIATORS OF " +
"{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +
"WHERE AssocClass = Win32_DiskDriveToDiskPartition"
Get-WmiObject -Query $partitions -ComputerName $WinHostName -Credential $cred| % {
$partition = $_
$drives = "ASSOCIATORS OF " +
"{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +
"WHERE AssocClass = Win32_LogicalDiskToPartition"
Get-WmiObject -Query $drives -ComputerName $WinHostName -Credential $cred| % {
New-Object -Type PSCustomObject -Property @{
Disk = $disk.DeviceID
DriveLetter = $_.DeviceID
VolumeName = $_.VolumeName
}
}
}
}
#Getting a disk serial number
foreach ($disk in $winDisk)
{
$disk | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null
$diskSerialNumber = $disk.SerialNumber
if ($disk.Model -notmatch 'VMware Virtual disk SCSI Disk Device')
{
if ($diskSerialNumber -match '^\S{12}$'){$diskSerialNumber = ($diskSerialNumber | foreach {[byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} } ) -join ''}
$disk.AltSerialNumber = $diskSerialNumber
}
}
#Searching all VM disks and matching them with Windows disks by their SerialNumber/UUID
$diskMaps = @()
foreach ($vmDisk in $vmDisks)
{
$vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')}
$windowsDisk = $winDisk | where {$_.SerialNumber -eq $vmDiskUuid}
if (-not $windowsDisk){$windowsDisk = $winDisk | where {$_.AltSerialNumber -eq $vmDisk.ScsiCanonicalName.substring(12,24)}}
$curDiskMap = "" | select vmDiskDatastore, vmDiskVmdk, vmDiskName, windowsDiskIndex, vmDiskUuid, windowsDeviceID, drives, volumes
$curDiskMap.vmDiskDatastore = $vmDisk.filename.split(']')[0].split('[')[1]
$curDiskMap.vmDiskVmdk = $vmDisk.filename.split(']')[1].trim()
$curDiskMap.vmDiskName = $vmDisk.Name
$curDiskMap.windowsDiskIndex = if ($windowsDisk){$windowsDisk.Index}else{"FAILED TO MATCH"}
$curDiskMap.vmDiskUuid = $vmDiskUuid
$curDiskMap.windowsDeviceID = if ($windowsDisk){$windowsDisk.DeviceID}else{"FAILED TO MATCH"}
$driveVolumes = $diskToDriveVolume | where {$_.Disk -eq $windowsDisk.DeviceID}
$curDiskMap.drives = $driveVolumes.DriveLetter
$curDiskMap.volumes = $driveVolumes.VolumeName
$diskMaps += $curDiskMap
}
$diskMaps = $diskMaps | sort {[int]$_.vmDiskName.split(' ')[2]}
$diskMaps | ft
该脚本还返回有关Windows中驱动器号和卷标的信息。
现在,我们可以轻松找到与给定虚拟vmdk磁盘匹配的Windows磁盘。
如果Windows中的虚拟磁盘是通过安装点连接的,则输出中将没有有关分配的驱动器号和卷标的信息。

