FMON
Enthusiast
Enthusiast

How to trace a VM disk to a guest disk.

How to trace a VM disk to a guest disk

No voodoo involved.  If you’re a Linux person then the mechanics of this process should work for you also.  For Windows people I'll include some PowerShell code that should work in Server 2008 and later (requires PowerCLI, and uses WMI).

How to trace a disk:

  • IF THE DISK IS NOT a physical mode RDM then simply match the ddb.uuid (virtual disk uuid) of the vmdk to the disk serial number seen in the guest OS.  To get the virtual disk uuid in PowerShell you can call the queryvirtualdiskuuid method of the VirtualDiskManager managed object (example in code).  If you’re not an administrator in VMware then you’ll need System.View privilege, and on every datastore with a disk you want to inspect you’ll need the Datastore.FileManagement privilege.

  • IF THE DISK IS a physical mode RDM then it’s a little trickier but not bad.  In this case the disk serial reported in the guest should display the LUN serial number from the array - NOT the virtual disk uuid of the RDM vmdk.  For these you need to try to match the disk serial of the guest with the last 24 characters of the ScsiCanonicalName of the VM hard disk.  This may or may not be a 1-step process.  The environment where I do things is hosted on NetApp storage, and the LUN serial number from NetApp arrays is in ASCII, so in order to match to the ScsiCanonicalName the LUN serial number first needs to be converted to HEX.  Not sure how other storage vendors are formatting their LUN serial numbers so you may need to tweak.  I’ve coded the script below to hopefully work if you’re on some other array vendor and they either A) use a 12-character ASCII LUN serial number, or B) present a 24-chracter HEX LUN serial number.

Works great in my environment but certainly not claiming it will work everywhere.  What I know for sure:

  1. Works on Windows VMs with between 1 and 4 SCSI adapters.  (Based on the methodology # SCSI adapters should not matter, nor should their model.)
  2. Works with physical mode RDM disks presented from NetApp storage.  (Never tried with virtual mode but don't they should work, possibly minor adjustments required.)
  3. 2003 servers don’t work because the Win32_DiskDrive class of WMI didn't provide a SerialNumber property in that version (probably solvable if you must).
  4. If anything exists in the guest that masks the disk serial number then this will not work.
  5. This won't work somewhere and probably lots of places.  Interested to hear your stories either way.

This code is just hacked together.  No error handling - if it bombs it bombs.  Just connect to your VI server (script does NOT do this) and edit $vmName to match the server you want to check.

Enjoy :smileymischief:

$vmName = "cheezburger"

## modification below here not necessary to run ##

#get windows disks via wmi

$cred = if ($cred){$cred}else{Get-Credential}

$win32DiskDrive  = Get-WmiObject -Class Win32_DiskDrive -ComputerName $vmName -Credential $cred

#get vm hard disks and vm datacenter and virtual disk manager via PowerCLI

#does not connect to a vi server for you!  you should already be connected to the appropraite vi server.

$vmHardDisks = Get-VM -Name $vmName | Get-HardDisk

$vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View

$virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager

#iterates through each windows disk and assign an alternate disk serial number value if not a vmware disk model

#required to handle physical mode RDMs, otherwise this should not be needed

foreach ($disk in $win32DiskDrive)

{

  #add a AltSerialNumber NoteProperty and grab the disk serial number

  $disk | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null

  $diskSerialNumber = $disk.SerialNumber

 

  #if disk is not a VMware disk set the AltSerialNumber property

  if ($disk.Model -notmatch 'VMware Virtual disk SCSI Disk Device')

  {

    #if disk serial number is 12 characters convert it to hex

    if ($diskSerialNumber -match '^\S{12}$')

    {

      $diskSerialNumber = ($diskSerialNumber | foreach {[byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} }  ) -join ''

    }

    $disk.AltSerialNumber = $diskSerialNumber

  }

}

#iterate through each vm hard disk and try to correlate it to a windows disk

#and generate some results!

$results = @()

foreach ($vmHardDisk in $vmHardDisks)

{

  #get uuid of vm hard disk / and remove spaces and dashes

  $vmHardDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmHardDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')}

 

  #match vm hard disk uuid to windows disk serial number

  $windowsDisk = $win32DiskDrive | where {$_.SerialNumber -eq $vmHardDiskUuid}

 

  #if windowsDisk not found then try to match the vm hard disk ScsiCanonicalName to the AltSerialNumber set previously

  if (-not $windowsDisk)

  {

    $windowsDisk = $win32DiskDrive | where {$_.AltSerialNumber -eq $vmHardDisk.ScsiCanonicalName.substring(12,24)}

  }

 

  #generate a result

  $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

}

#sort and then output the results

$results = $results | sort {[int]$_.vmHardDiskName.split(' ')[2]}

$results | ft -AutoSize

Tags (3)
7 Replies
jcampos3493
Contributor
Contributor

FMON, thanks for the awesome script. I am however having some issues with it. It looks like I'm only getting the "windowsDiskIndex, windowsDiskSerialNumber, & windowsDiskAltSerialNumber" for only the non RDM disks...

vmHardDiskName windowsDiskIndex windowsDiskSerialNumber          vmHardDiskUuid                   windowsDiskAltSerialNumber vmHardDiskScsiCanonicalName

-------------- ---------------- -----------------------          --------------                   -------------------------- ---------------------------

Hard disk 1                   0 6000c299634fc97de071566b9f071359 6000C299634fc97de071566b9f071359

Hard disk 2     FAILED TO MATCH FAILED TO MATCH                  6000C297d78efef9c646ebe808fdb741 FAILED TO MATCH            naa.600601605f61310011e4a934806be511

Hard disk 3     FAILED TO MATCH FAILED TO MATCH                  6000C29f7365ddbc290d9db73d4f9628 FAILED TO MATCH            naa.600601605f6131001711716a7d6be511

Hard disk 4     FAILED TO MATCH FAILED TO MATCH                  6000C290747b10d4b2c197f6853e80ae FAILED TO MATCH            naa.600601605f61310079cfc466806be511

Hard disk 5     FAILED TO MATCH FAILED TO MATCH                  6000C295dff4205885458efd9ea614e0 FAILED TO MATCH            naa.600601605f6131007959baf37d6be511

Hard disk 6                   1 6000c29775446efa07b7387b1d46441e 6000C29775446efa07b7387b1d46441e

Hard disk 7                   2 6000c2973503e05024a2795874933066 6000C2973503e05024a2795874933066

0 Kudos
mserrano1982
Contributor
Contributor

Hi FMON,

excellent script, close to what I was looking for.

I found this issue with pRDM : "FAILED TO MATCH" on "windowsDiskIndex" and "windowsDiskSerialNumber"

Any idea mate?

0 Kudos
AlbertWT
Virtuoso
Virtuoso

FMON ,

Thanks for sharing the script.

With no RDM in the VM attached, does the windowsDiskAltSerialNumber and vmHardDiskScsiCanonicalName column supposed to be empty?

/* Any kind of comment or input would be greatly appreciated */
0 Kudos
hharold
Enthusiast
Enthusiast

Hello,

Although I really like the solution, and I think I know the answer to this question, but then just to confirm....

Is there any way to map the VM .vmdk file to a guest disk, only based on the info vCenter and the VM tools provide?
(So with no access to the VM or its WMI information)

Just to confirm.


Cheers,
Harold

LucD
Leadership
Leadership

No (but you knew that :smileygrin:)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Pcliba
Contributor
Contributor

First of all thanks for your script FMON. Earlier this year I had the problem to match OS disk with vm vHDD while writing an autoextend script for our windows servers.

I then tried your script. It didn't work for my environment, but it helped me a lot to solve my problem.

Here is the link to my script proposal, like FMONs, just hacked together with no real error handling and I guess with many need for improvement.

Perhaps this script helps some of you or somebody wants to improve it. I'm open to suggestions!

Match OS Disk - vmware vHDD · GitHub

The script uses:

- Powercli

- Powershell

- WMI

Prerequisites:

- disk.EnableUUID="true"

- User for Invoke-VMScript with appropriate rights

- current vmware tools version

Cheers!

0 Kudos
MMITAmsterdam
Contributor
Contributor

Great script! Took ages to find something like this.

Thanks for sharing.

José

0 Kudos