VMware: Matching Attached vDisk UUID to Guest Windows HDD
Ever wanted to remove an unused hard drive from a VM without removing the wrong one?
Sometimes VMs will have multiple vDisks with the same size, making it difficult to determine which one is the drive in Windows you wanted to remove.
I present to you… a script.
Done groaning yet? Well good!
There are many commands, snippets and even other scripts that will do what this one does. But this one is special, because it was made by me. So… yeah, that’s pretty much it.
Oh, almost fogot! It’s been updated to work with WindowsManagementFramework 5.1 and PowerCLI 6.5!
Open a PowerShell command line using an account that has approporiate rights to your vCenter server.
Function Get-RequiredModule { Param([string]$name) if(!(Get-Module $name)){if(!(Get-Module -ListAvailable | Where-Object {$_.name -eq $name})){write-host "Required module $($name) missing."} else { Import-Module $name }} else { $true } } # Load the required modules Get-RequiredModule -name "VMware.PowerCLI" # Check if required modules are loaded, if not, break out of script. if(!(Get-RequiredModule -name "VMware.PowerCLI")){Break} # Modify this section as needed $VC=@() $vmName=@() # Change these defaults to suit your environment $dft_VC = "vCenter.domain.com" $dft_vmName = "Virtual Machine Name" # Get inputs from user, with default values $VC = Read-Host -Prompt "Input your vCenter Server here (Press enter for: $($dft_VC))" $vmName = Read-Host -Prompt "Input your Virtual Machine name here (Press enter for: $($dft_vmName))" # Assign default values to the field if no user input was given If(!($VC)){$VC=$dft_VC} If(!($vmName)){$vmName=$dft_vmName} # Do not modify below here Connect-VIServer -Server "$vc" -Force $win32DiskDrive = Get-WmiObject -Class Win32_DiskDrive -ComputerName $vmName $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 | % { $disk = $_ $partitions = "ASSOCIATORS OF " + "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " + "WHERE AssocClass = Win32_DiskDriveToDiskPartition" Get-WmiObject -Query $partitions -ComputerName $vmName | % { $partition = $_ $drives = "ASSOCIATORS OF " + "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " + "WHERE AssocClass = Win32_LogicalDiskToPartition" Get-WmiObject -Query $drives -ComputerName $vmName | % { New-Object -Type PSCustomObject -Property @{ Disk = $disk.DeviceID DriveLetter = $_.DeviceID VolumeName = $_.VolumeName } } } } foreach ($diskDrive in $win32DiskDrive) { $diskDrive | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null $diskSerialNumber = $diskDrive.SerialNumber if ($diskDrive.Model -notmatch 'VMware Virtual disk SCSI Disk Device') { if ($diskSerialNumber -match '^\S{12}$'){$diskSerialNumber = ($diskSerialNumber | foreach { [byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} }) -join ''} $diskDrive.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