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 PowerShe...
See more...
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: Works on Windows VMs with between 1 and 4 SCSI adapters. (Based on the methodology # SCSI adapters should not matter, nor should their model.) 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.) 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). If anything exists in the guest that masks the disk serial number then this will not work. 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