I've been searching all over for a way I could match disks inside windows to vmware's harddisk
The problem is when I have disks with same scsi id on more than one scsicontroller (for ex. (1:0) and (0:0))
I found some scripts that compare the scsicontroller.bus number with the windows scsiport -1 but its not always the case..sometimes its -2 and sometimes its equal with no change. Any ideas? thanks in advance
Welcome to the Community,
unfortunately I cannot provide a solution (still looking for one myself). However, what I do as a workaround to be able to reliably match the virtual disks with the guest disks, is to use slightly different virtual disk sizes.
André
I'm afraid there is currently no foolproof method to accomplish that :smileycry:
Depending on the configuration of your VMs there are some methods that will work (like the small size differences mentioned by André), but no general method afaik.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi everybody,
Hope this two VMware KB Articles helps.
Determining which drives and volumes match which disks in a Windows virtual machine (2021947)
http://kb.vmware.com/kb/2021947
Cheers!
Regards,
-Marvin Marcos/VMware TSE
This is the only fool-proof method I have found. Compare the VMname.vmx values to the Location and Target ID from disk properties in Windows Disk Management.
I made a support post on my blog.
http://echohellowordl.blogspot.com/2014/02/match-virtual-hard-disks-in-virtual.html
Afaik, you can only use the Location when the VM runs a recent Windows OS.
So no solution for older Windows OS and any *nix OS.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Many thx myVirtualHell, your soulution is not very comfortable one, but at least a workaround.
Hi not sure if you have already found the solution but I managed to do this mapping vm uuid and windisk serial no code below $DiskInfo = @() Connect-VIServer $creds = Get-Credential $computers = "" foreach ($computername in $computers) { $windiskdrives = Get-WmiObject -computername $computername -Class Win32_DiskDrive -Property * -Credential $creds $windiskpartitions = Get-WmiObject -ComputerName $computername -Class win32_diskpartition -Property * -Credential $creds $vmdiskdrives = Get-harddisk -vm $computername $VMScsiController = Get-ScsiController -VM $computername foreach ($vmdiskdrive in $vmdiskdrives) { $VirtualDisk = "" | Select SystemName, SCSIController, DiskName, SCSI_Id, DiskFile, VMDiskSize, WindowsDisk, DriveLetter, Description, WinDisksize, winSCSIID $VirtualDisk.systemname = $computername $VMUUID = ($vmdiskdrive.ExtensionData.Backing.uuid).replace("-", "") $SCSICont = $VMScsiController | where { $_.extensiondata.key -eq $vmdiskdrive.extensiondata.controllerkey } $VirtualDisk.SCSIController = $SCSICont.name $VirtualDisk.DiskName = $vmdiskdrive.name $VirtualDisk.SCSI_Id = "$($vmdiskdrive.ExtensionData.controllerkey - 1000) : $($vmdiskdrive.ExtensionData.unitnumber)" $VirtualDisk.DiskFile = $vmdiskdrive.ExtensionData.Backing.FileName $VirtualDisk.VMDiskSize = $vmdiskdrive.ExtensionData.CapacityinKB * 1KB / 1GB $diskmatch = $windiskdrives | where { $_.SerialNumber -eq $VMUUID } if ($DiskMatch) { $VirtualDisk.Winscsiid = "$($diskmatch.SCSIport - 2) : $($diskmatch.SCSITARGETID)" $VirtualDisk.WindowsDisk = "Disk $($diskmatch.Index)" $match1 = $windiskpartitions | where { $_.diskindex -eq $DiskMatch.index } ForEach ($partition in $match1) { $logicaldisk = $partition.psbase.GetRelated('Win32_LogicalDisk') if ($logicaldisk.name -ne $null) { $VirtualDisk.DriveLetter = $logicaldisk.DeviceID $VirtualDisk.Description = $logicaldisk.VolumeName $VirtualDisk.windisksize = $logicaldisk.Size / 1GB } } } $DiskInfo += $VirtualDisk } } $DiskInfo | Out-GridView
Hi George, I've found exactly the same problem, and reviewing a number of articles no one has seemed to reliably sort out the SCSI ID when multiple controllers are involved. Frustratingly the value you need is not available through the WMI interface and a registry key is needed.
Here is some PS code which works for the LSI VMware adapter, if you have other types in your environment I'd be interested to see the output.
Function Get-VolumesEX() { $volumelist= New-Object System.Collections.ArrayList $SCSIControllers = Get-WmiObject -class Win32_SCSIController foreach ($SCSIController in $SCSIControllers) { $SCSIControllerRegKeys = Get-ItemProperty -path "hklm:\SYSTEM\CurrentControlSet\Enum\$($SCSIController.DeviceID)" $Disks=(gwmi -query ('ASSOCIATORS OF {' + $SCSIController.path + '} WHERE ResultClass=Win32_PnPEntity' ))| Where {$_.Service -eq "disk"} forEach ($Disk in $Disks) { $DiskDrive = (gwmi -query ('ASSOCIATORS OF {' + $Disk.path + '} WHERE ResultClass=Win32_DiskDrive')) $DiskPartitions = gwmi -query ('ASSOCIATORS OF {' + $DiskDrive.path + '} WHERE ResultClass=Win32_DiskPartition') ForEach ($DiskPartition in $DiskPartitions) { $LogicalDisks = gwmi -query ('ASSOCIATORS OF {' + $DiskPartition.path + '} WHERE ResultClass=Win32_LogicalDisk') ForEach ($LogicalDisk in $LogicalDisks) { If ($SCSIController.Name -eq "LSI Adapter, SAS 3000 series, 8-port with 1068" -and $Disk.Name -eq "VMware Virtual disk SCSI Disk Device") { # VMWARE DEVICE / ADD SCSI BUS AS PER SETTINGS IN VSPHERE / THIS MAY CHANGE FOR OTHER VMWARE ADAPTERS # $SCSIControllerVMWareID = $SCSIControllerRegKeys.UINumber # #controller 0 = location 160 #controller 1 = location 256 #controller 2 = location 161 #controller 3 = location 224 $VMWareSCSIController = {Switch ($SCSIControllerVMWareID) { "160" {'0';Break} "256" {'1';Break} "161" {'2';Break} "224" {'3';Break} Default {'Unknown'} }}.InvokeReturnAsIs() $NewVolume = New-Object PSObject -Property @{ SCSIController = $SCSIController.Name; DiskName =$Disk.Name ; DiskPartiion = $DiskPartition.Name ; DriveLetter = $LogicalDisk.DeviceID ; Label =$LogicalDisk.VolumeName ; SCSI = "($($VMWareSCSIController):$($DiskDrive.SCSITargetId))" ; Capacity =$LogicalDisk.Size ; FreeSpace =$LogicalDisk.FreeSpace } }else{ $NewVolume = New-Object PSObject -Property @{ SCSIController = $SCSIController.Name; DiskName =$Disk.Name ; DiskPartiion = $DiskPartition.Name ; DriveLetter = $LogicalDisk.DeviceID ; Label =$LogicalDisk.VolumeName ; SCSI = "($($DiskDrive.SCSIBus):$($DiskDrive.SCSITargetId))" ; Capacity =$LogicalDisk.Size ; FreeSpace =$LogicalDisk.FreeSpace } } $volumelist.Add($NewVolume) | out-null } } } } return $volumelist }
Script looks great, but as with all scripts I come across that try to retrieve the SCSI ID, it stumbles on the fact that the registry key it tries to query doesnt exist.
I forgot to add that scripts never work that employ more than 1 controller, i.e. SCSI ID's that start 1:0
Its not a coincidence a I have run it on multiple VMs with the same issue.
There has to be a way to get these details using WMI?
Hi All,
I know this is a old threat, but just an update.
With the scsitargetid from Windows side and Disk ID you can identify from both sides.
Here is a great post from Nick Colyer that I use when I need to identify both, and I had always the right Disks.
http://2ninjas1blog.com/how-to-match-and-correlate-windows-scsi-disk-ids-with-vmware-vmdks/
Hope this can help.
all those referenced VMware KB Articles lead into en empty page!
- The requested page may have been moved or deleted
- You may have used an outdated or broken link
- You may have typed the address (URL) incorrectly
Please use the search box to find alternative solutions.
When you search for the topic, or the KB Number you will find nothing!
Have they been removed, or changed?
This is really frustrating.
DaHess- I would also be interested in knowing what those links said. But here's how I'm doing this.
Trace the same way as you would for a physical server - by the disk serial number. (Not LUN ID, although people do trace disks in physical servers that way also. That's fine most of the time but there can be duplicate LUN IDs. When that happens you have to use the serial number. In scripts you should always use the disk serial number.)
To find the serial number of the disk in VMware:
$virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager
$virtualDiskManager.queryvirtualdiskuuid($vmHardDisk.Filename, $vmDatacenterView.MoRef)
RESULT: 60 00 c2 97 68 54 f3 81-ac 91 2e 6a 13 37 a4 fa
To find the serial number of the disk in Windows:
Get-WmiObject -Class Win32_DiskDrive -ComputerName $vmName -Credential $cred | select -expand SerialNumber
#RESULT: 6000c2976854f381ac912e6a1337a4fa
The rest should be easy. And a similar solution in Linux should be possible. No SCSI madness which is horribly unreliable depending on your environment.
The above should work for disks that are not physical mode RDMs. For those, match the ScsiCanonicalName of the disk in VMware to the serial number of the disk in Windows. Some hex conversion may be required.
More details here, including a PowerShell script, and some caveats and known issues: How to trace a VM disk to a guest disk.
This is a simple PowerShell Script I use:
———————————————-
$SCSI = 0
$PCIS = (1600,1700,1800,1900,1501,1601,1701,1801,1901)
$SCSIList = Get-Disk | SELECT Location
FOREACH ($PCI in $PCIS)
{
IF ($SCSIList.Location -like '*$PCI*')
{
$SCSI++
Set-Variable -Name '$PCI' -Value $SCSI
}
}
Get-Disk | SELECT `
@{Name='Win Disk Number';Expression={$_.Number}},
@{Name='VMware SCSI';Expression={$_.Location.Trim('PCIROOT(0)#PCI(').Replace(')#PCI(0000)#SAS(P00T',':').Replace('00)','').Replace('1500','0').Replace('1501',$1501).Replace('1600',$1600).Replace('1601',$1601).Replace('1700',$1700).Replace('1701',$1701).Replace('1800',$1800).Replace('1801',$1801).Replace('1900',$1900).Replace('1901',$1901).Replace(':0',':').Trim('L')}},
@{Name='Size GB';Expression={$_.Size/1GB}},
PartitionStyle | Sort-Object 'Win Disk Number' | FT -AutoSize -ErrorAction Stop
———————————————-
I assuming that VMware and Windows are ordering de Disk Locations numbers differently and that causes the issue.
Windows: 1500,1501,1600,1601…
VMWare: 1500,1600,….1501,1601….
The PowerShell Script only works with Windows Server 2012 and higher OS versions as [Get-Disk] is not supported in older Server OS versions.
Please let me know if this works for you.
Thx
Kittens die when you match disks via SCSI attributes. And it's horribly inaccurate.
Here is how to do it accurately and without the unnecessary kitten deaths:
$vmName = "HolyGrail"
## modification below here not necessary to run
$cred = if ($cred){$cred}else{Get-Credential}
$win32DiskDrive = Get-WmiObject -Class Win32_DiskDrive -ComputerName $vmName -Credential $cred
$vmHardDisks = Get-VM -Name $vmName | Get-HardDisk
$vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View
$virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager
foreach ($disk in $win32DiskDrive)
{
$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
}
}
$results = @()
foreach ($vmHardDisk in $vmHardDisks)
{
$vmHardDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmHardDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')}
$windowsDisk = $win32DiskDrive | where {$_.SerialNumber -eq $vmHardDiskUuid}
if (-not $windowsDisk){$windowsDisk = $win32DiskDrive | where {$_.AltSerialNumber -eq $vmHardDisk.ScsiCanonicalName.substring(12,24)}}
$result = "" | select vmName,vmHardDiskDatastore,vmHardDiskVmdk,vmHardDiskName,windowsDiskIndex,windowsDiskSerialNumber,vmHardDiskUuid,windowsDiskAltSerialNumber,vmHardDiskScsiCanonicalName
$result.vmName = $vmName.toupper()
$result.vmHardDiskDatastore = $vmHardDisk.filename.split(']')[0].split('[')[1]
$result.vmHardDiskVmdk = $vmHardDisk.filename.split(']')[1].trim()
$result.vmHardDiskName = $vmHardDisk.Name
$result.windowsDiskIndex = if ($windowsDisk){$windowsDisk.Index}else{"FAILED TO MATCH"}
$result.windowsDiskSerialNumber = if ($windowsDisk){$windowsDisk.SerialNumber}else{"FAILED TO MATCH"}
$result.vmHardDiskUuid = $vmHardDiskUuid
$result.windowsDiskAltSerialNumber = if ($windowsDisk){$windowsDisk.AltSerialNumber}else{"FAILED TO MATCH"}
$result.vmHardDiskScsiCanonicalName = $vmHardDisk.ScsiCanonicalName
$results += $result
}
$results = $results | sort {[int]$_.vmHardDiskName.split(' ')[2]}
$results | ft -AutoSize
How the above method works is described here: How to trace a VM disk to a guest disk.
:smileycool:
Hallo FMON,
My intension was to check if the “Location Path Format” of the SCSI disks order of Windows vs VMware’s VM is really the cause of the problem and to have that checked by others.
I’m no VMware expert (I’m just a SQL DBA).
That was the reason why I had mentioned in my post to “please let me know if this works for you”.
We have some VM’s with 4 PVSCSI adapters (and with up to 60 disks).
On this servers (and lots of other servers with lees and different SCSI adapters) we tested and compared de SCSI Addresses vs the Windows Disk Location Paths.
The result was always the same order:
Windows: 1500,1501,1600,1601,1700,1701…
VMWare: 1500,1600,1700,….1501,1601,1701….
I would be glad if you prove me wrong (to prevent misconfiguration of our servers in de future).
This should not be difficult for you, as my method is “horribly inaccurate” according to you and you are probably more experienced with the VNware environment.
With your script I’m getting [FAILED TO MATCH] for all disks.
Assuming that I do not have the necessary access rights within VMware.
Could you please test the script (if you want) and provide me with info of the scenarios when it has or will not work.
Then I could test it in our test environment.
And if you are right, I will give you credit for saving the Kittens
Hey Tamim-
Glad you too are concerned about the kittens. It has been bad around here for them :smileymischief:
Sure I'll be happy to spend some cycles trying to blow up your method. Probably this weekend or next week sometime. Unfortunately you are relying on Get-Disk which is 2012 and later and most of my interesting things are still 2008R2. Have you done much testing in a non-static environment with disks being added and removed?
With my method did you get some console errors? If so what? If you're not a VMware admin then there are a couple of read privileges you'll need from your VMware people. The link in my previous post has some details.
Hey FMON
Thanks for your fast reaction.
I really appreciate your assistance
Attached is a PoweShell Script that should do (almost) the same as the previous script and work with W2008 (it uses DiskPart).
The result of running your Script is also attached as TXT file (on a Server with 60 disks).
As for testing:
Yes I have had added and removed SCSI Disks to a VM with 4 PVSCSI adapters to test and had no problems with my script.
Hallo FMON,
First of all my best wishes for the year 2017
... i'm still waiting.
Regards,
Tamim
I'm getting most of the information I need from this script but its not giving me the "WindowsDiskIndex" or "WindowsDiskSerialNumber" for any of my Physical RDMs. Can you please advise.
Thanks.