Matching Windows Disks to VMware VMDK Files
I have been looking for this for at long time and there are some script on, VMware forums and other places, that can do this, but I was satisfied with them, since they did not give me all the information i needed.
So began to peace some of them tougher to a new one, And this one will return datastorename, path/filename, drive letters/volumename and other.
This script will connect på vCenter, find the VM, ask for creditials for the Windows server, at collect all the information and put in “$result”.
It first matches the VMDK file Unique ID (UUID) whit the Windows harddisk Serial, number, and finds the Windows disk deviceID. this is it then matches all the partitions, to find the drive letters and volume names.
## Modufy this sections as needed #import-module -name vmwre.powercli connect-viserver <vCenter name> $vmName = "<VM Name>" ## 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 $diskToDriveVolume = Get-WmiObject Win32_DiskDrive -ComputerName $vmName -Credential $cred| % { $disk = $_ $partitions = "ASSOCIATORS OF " + "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " + "WHERE AssocClass = Win32_DiskDriveToDiskPartition" Get-WmiObject -Query $partitions -ComputerName $vmName -Credential $cred| % { $partition = $_ $drives = "ASSOCIATORS OF " + "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " + "WHERE AssocClass = Win32_LogicalDiskToPartition" Get-WmiObject -Query $drives -ComputerName $vmName -Credential $cred| % { New-Object -Type PSCustomObject -Property @{ Disk = $disk.DeviceID DriveLetter = $_.DeviceID VolumeName = $_.VolumeName } } } } 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, windowsDeviceID, drives, volumes $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.windowsDeviceID = if ($windowsDisk){$windowsDisk.DeviceID}else{"FAILED TO MATCH"} $driveVolumes = $diskToDriveVolume | where {$_.Disk -eq $windowsDisk.DeviceID} $result.drives = $driveVolumes.DriveLetter $result.volumes = $driveVolumes.VolumeName $results += $result } $results = $results | sort {[int]$_.vmHardDiskName.split(' ')[2]} $results | ft -AutoSize
The output looks like this
I have not tested this in all scenarios, so do your own testing before using this scripts.
Using this script and method is at your own risk
Notes.
The script does not always works if using mount points i windows.
The script ONLY works on VMDK files and virtual RDMs, and not on physical RDMs (the scripts fails if you are using physical RDMs on the VM).
Update 3 April 2002: with vSphere 7 and PowerCLI this is build in as a cmdlets, see here.
Works like a charm, good work and much needed 🙂
Super Script! Great work!
Can you please help. I am getting following error when trying to fetch details from WINDOWS platform system, post providing correct credential
PowerCLI E:\> .\dskmpCh1.ps1
Name Port User
—- —- —-
c1srv2vvc01 443 BALICIN\Drmadmvc
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
At E:\dskmpCh1.ps1:7 char:20
+ $win32DiskDrive = Get-WmiObject -Class Win32_DiskDrive -ComputerName $vmName -C …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
At E:\dskmpCh1.ps1:11 char:22
+ $diskToDriveVolume = Get-WmiObject Win32_DiskDrive -ComputerName $vmName -Creden …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Exception calling “QueryVirtualDiskUuid” with “2” argument(s): “The object has already been deleted or has not been completely created”
At E:\dskmpCh1.ps1:45 char:3
+ $vmHardDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmHardDisk.Filenam …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException
You cannot call a method on a null-valued expression.
At E:\dskmpCh1.ps1:47 char:66
+ if (-not $windowsDisk){$windowsDisk = $win32DiskDrive | where {$_.AltSerialNum …
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Exception calling “QueryVirtualDiskUuid” with “2” argument(s): “The object has already been deleted or has not been completely created”
At E:\dskmpCh1.ps1:45 char:3
+ $vmHardDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmHardDisk.Filenam …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException
You cannot call a method on a null-valued expression.
At E:\dskmpCh1.ps1:47 char:66
+ if (-not $windowsDisk){$windowsDisk = $win32DiskDrive | where {$_.AltSerialNum …
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
vmName vmHardDiskDatastore vmHardDiskVmdk vmHardDiskName windowsDiskIndex windowsDiskSerialNumber vmHardDiskUuid windowsDeviceID drives volumes
—— ——————- ————– ————– —————- ———————– ————– ————— —— ——-
C5SRW2TST01 HP_SSD_Win11 C5SRW2TST01/C5SRW2TST01.vmdk Hard disk 1 FAILED TO MATCH FAILED TO MATCH FAILED TO MATCH
C5SRW2TST01 HP_SSD_Win11 C5SRW2TST01/C5SRW2TST01_1.vmdk Hard disk 2 FAILED TO MATCH FAILED TO MATCH FAILED TO MATCH
PowerCLI E:\cajetan\cajetan123>
Look like the account you use, do not have administrativ right in the Windows, on the VM.
Great script. Pretty complex to get all things puzzled together from different places.
I wrote a disk resize script Windows/VMware. The only thing missing is that it associates a drive letter input directly with the right disk on the VM.
Hi Enrico. Were you able to finish your resize script? I’m trying to implement a auto resize script on my Vmware but I’m still unable to find something that associates the drive letter to the correct VM HDD.
No, have not found a method for the Windows drives that used as mount point.
The script is also only for finde the correlation between VMDK and drive letters, I have not looked into, doing the resizing, with this script.
can you helpme with this error
Exception calling “QueryVirtualDiskUuid” with “2” argument(s): “Invalid datastore path ‘[XXXXXXXXX] XXXXX.vmdk’.
At line:4 char:3
+ $vmHardDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmHardD …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException
not sure what’s wrong.
Did you remember to uncomment the “import-module -name vmware.powercli”
I have testet this with PowerCLI 10.x.
I have not tested this on vSAN and VVOL.
I just came across this. Exactly what I needed. Thank you for putting in the time and sharing it out.
Hi,
Could you please let me know, why I am getting below error on few EMC VNX devices
Exception calling “QueryVirtualDiskUuid” with “2” argument(s): “A general system error occurred: No such device”
At D:\myreports\Disk_Info\match_disk_info2.ps1:100 char:3
+ $vmHardDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmHardD …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException
The script does not work with physical RDMs, only VMDK files and virtual RDM. I don’t have a solution for the physical RDMs.