将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中的虚拟磁盘是通过安装点连接的,则输出中将没有有关分配的驱动器号和卷标的信息。