This is a follow up on a post I did a couple of weeks ago to create a mapping table between Windows- and VMware hard disks. In another previous post PowerCLI: Get WMI info from isolated guests, I showed you how to get WMI info from a guest without using the guest’s network. I used this technique to enhance my mapping table script.
You need to login to both the ESX host and the Windows guest seperately, so there’s no more need for the user running the script to have administrator permissions on the guest. Multiple domains aren’t an issue anymore and neither are firewalls.
Remember: this only works when VMware Tools are installed
# This script requires PowerCLI 4.0 U1 # # Create Disk Mapping Table v2.0 # Created by Arnim van Lieshout # Http://www.van-lieshout.com # Initialize variables # $VCServerList is a comma-separated list of vCenter servers $VCServerList = "vcenter01","vcenter02" $DiskInfo= @() # Set Default Server Mode to Multiple Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false | Out-Null # Connect to vCenter Server(s) foreach ($VCServer in $VCServerList) {Connect-VIServer -Server "$VCServer" | Out-Null} $Vm = Read-Host "Enter VMName to create disk mapping for" if (($VmView = Get-View -ViewType VirtualMachine -Filter @{"Name" = $Vm})) { $ESXHost = Get-VMHost -id $VmView.Summary.Runtime.Host # Get credentials $HostCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter ESX host credentials for $ESXHost", "root", "") $GuestCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter Guest credentials for $VM", "", "") #Get WMI info $Error.Clear() $Out = Invoke-VMScript "wmic path win32_diskdrive get Index, SCSIPort, SCSITargetId /format:csv" -vm $VM -HostCredential $HostCred -GuestCredential $GuestCred -scripttype "bat" if (!$error) { $FileName = [System.IO.Path]::GetTempFileName() $Out.Substring(2) > $FileName $WinDisks = Import-Csv $FileName Remove-Item $FileName foreach ($VirtualSCSIController in ($VMView.Config.Hardware.Device | where {$_.DeviceInfo.Label -match "SCSI Controller"})) { foreach ($VirtualDiskDevice in ($VMView.Config.Hardware.Device | where {$_.ControllerKey -eq $VirtualSCSIController.Key})) { $VirtualDisk = "" | Select SCSIController, DiskName, SCSI_Id, DiskFile, DiskSize, WindowsDisk $VirtualDisk.SCSIController = $VirtualSCSIController.DeviceInfo.Label $VirtualDisk.DiskName = $VirtualDiskDevice.DeviceInfo.Label $VirtualDisk.SCSI_Id = "$($VirtualSCSIController.BusNumber) : $($VirtualDiskDevice.UnitNumber)" $VirtualDisk.DiskFile = $VirtualDiskDevice.Backing.FileName $VirtualDisk.DiskSize = $VirtualDiskDevice.CapacityInKB * 1KB / 1GB # Match disks based on SCSI ID $DiskMatch = $WinDisks | ?{($_.SCSIPort – 1) -eq $VirtualSCSIController.BusNumber -and $_.SCSITargetID -eq $VirtualDiskDevice.UnitNumber} if ($DiskMatch){ $VirtualDisk.WindowsDisk = "Disk $($DiskMatch.Index)" } else {Write-Host "No matching Windows disk found for SCSI id $($VirtualDisk.SCSI_Id)"} $DiskInfo += $VirtualDisk } } $DiskInfo | Out-GridView } else {Write-Host "Error Retrieving WMI info from guest"} } else {Write-Host "VM $Vm Not Found"} Disconnect-VIServer * -Confirm:$false
Since I like using the VESI, I integrated the script into the EcoShell with just a few minor adjustments. You can also use PowerGUI instead.
Just create a new Script node and paste the following code:
if ($global:defaultviservers) { $DiskInfo= @() $Vm = Read-Host "Enter VMName to create disk mapping for" if (($VmView = Get-View -ViewType VirtualMachine -Filter @{"Name" = $Vm})) { $ESXHost = Get-VMHost -id $VmView.Summary.Runtime.Host $HostCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter ESX host credentials for $ESXHost", "root", "") $GuestCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter Guest credentials for $VM", "", "") $Out = Invoke-VMScript "wmic path win32_diskdrive get Index, SCSIPort, SCSITargetId /format:csv" -vm $VM -HostCredential $HostCred -GuestCredential $GuestCred -scripttype "bat" $FileName = [System.IO.Path]::GetTempFileName() $Out.Substring(2) > $FileName $WinDisks = Import-Csv $FileName Remove-Item $FileName foreach ($VirtualSCSIController in ($VMView.Config.Hardware.Device | where {$_.DeviceInfo.Label -match "SCSI Controller"})) { foreach ($VirtualDiskDevice in ($VMView.Config.Hardware.Device | where {$_.ControllerKey -eq $VirtualSCSIController.Key})) { $VirtualDisk = "" | Select SCSIController, DiskName, SCSI_Id, DiskFile, DiskSize, WindowsDisk $VirtualDisk.SCSIController = $VirtualSCSIController.DeviceInfo.Label $VirtualDisk.DiskName = $VirtualDiskDevice.DeviceInfo.Label $VirtualDisk.SCSI_Id = "$($VirtualSCSIController.BusNumber) : $($VirtualDiskDevice.UnitNumber)" $VirtualDisk.DiskFile = $VirtualDiskDevice.Backing.FileName $VirtualDisk.DiskSize = $VirtualDiskDevice.CapacityInKB * 1KB / 1GB $DiskMatch = $WinDisks | ?{($_.SCSIPort – 1) -eq $VirtualSCSIController.BusNumber -and $_.SCSITargetID -eq $VirtualDiskDevice.UnitNumber} if ($DiskMatch){ $VirtualDisk.WindowsDisk = "Disk $($DiskMatch.Index)" } else {Write-Host "No matching Windows disk found for SCSI id $($VirtualDisk.SCSI_Id)"} $DiskInfo += $VirtualDisk } } $DiskInfo } else {[System.Windows.Forms.MessageBox]::Show("VM $Vm Not Found",'Virtual Machine not Found',[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null} } Else { [System.Windows.Forms.MessageBox]::Show('You must connect to one or more hosts before you can use this node. Please click on the ''Managed Hosts'' node of the VMware PowerPack, connect to one or more of the servers you have configured there, and then try again.','Connection not established',[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null }
Example output from the EcoShell:


on Feb 3rd, 2010 at 11:50 pm
[...] I recently made some improvements that get rid of these limitations. Read all about it in Match VM and Windows harddisks part 2. [...]