VMware Cloud Community
GeorgeSm
Contributor
Contributor

Match correctly windows disk to vmware harddisk

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

28 Replies
a_p_
Leadership
Leadership

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é

LucD
Leadership
Leadership

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

marvinmarcos
VMware Employee
VMware Employee

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

Match Windows disk drive mapping to virtual machine SCSI controller settings (2051606)

http://kb.vmware.com/kb/2051606

Cheers!

Regards,

-Marvin Marcos/VMware TSE

myVirtualHell
Contributor
Contributor

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

LucD
Leadership
Leadership

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

Reply
0 Kudos
RobertAnders
Contributor
Contributor

Many thx myVirtualHell, your soulution is not very comfortable one, but at least a workaround.

Reply
0 Kudos
DollieDaydream
Contributor
Contributor

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

MartinSiddall
Contributor
Contributor

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
}

Reply
0 Kudos
Mike_Yazbeck
Enthusiast
Enthusiast

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?

Reply
0 Kudos
LucianoPatrão

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.

Luciano Patrão

VCP-DCV, VCAP-DCV Design 2023, VCP-Cloud 2023
vExpert vSAN, NSX, Cloud Provider, Veeam Vanguard
Solutions Architect - Tech Lead for VMware / Virtual Backups

________________________________
If helpful Please award points
Thank You
Blog: https://www.provirtualzone.com | Twitter: @Luciano_PT
Reply
0 Kudos
DaHess_DNVGL
Contributor
Contributor

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.

Reply
0 Kudos
FMON
Enthusiast
Enthusiast

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.

Reply
0 Kudos
Tamim02
Contributor
Contributor

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

FMON
Enthusiast
Enthusiast

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:

Reply
0 Kudos
Tamim01
Contributor
Contributor

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 Smiley Happy

FMON
Enthusiast
Enthusiast

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.

Reply
0 Kudos
Tamim01
Contributor
Contributor

Hey FMON
Thanks for your fast reaction.
I really appreciate your assistance Smiley Happy
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.

Reply
0 Kudos
Tamim02
Contributor
Contributor

Hallo FMON,

First of all my best wishes for the year 2017  Smiley Happy
... i'm still waiting.

Regards,
Tamim

Reply
0 Kudos
jcampos3493
Contributor
Contributor

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.

Reply
0 Kudos