Arnim van Lieshout Rotating Header Image

PowerCLI: Match VM and Windows harddisks – Part 2

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:

VMware VirtualCenter 2.5 Update 6

Last friday VMware released Virtual Center 2.5 update 6.  Most interesting new feature is that it now supports customization for both Windows 7 and Windows Server 2008 R2.

From the Release notes:

What’s New

Guest Operating Systems Customization Improvements

Customization support for the following guest operating systems has been added in this release:
For more complete information about supported guests included in this release, see the VMware Compatibility Guide.

  • Windows 7 Enterprise (32-bit and 64-bit)
  • Windows 7 Ultimate (32-bit and 64-bit)
  • Windows 7 Professional (32-bit and 64-bit)
  • Windows 7 Home Premium (32-bit and 64-bit)
  • Windows Server 2008 R2 Standard Edition (64-bit)
  • Windows Server 2008 R2 Enterprise Edition (64-bit)
  • Windows Server 2008 R2 Datacenter Edition (64-bit)
  • Windows Server 2008 R2 Web Server (64-bit)

There are a lot of other updates and bugfixes that come with this release, so when you’re still running a VI3 environment, my advice is to upgrade to this latest version.

PowerShell / PowerCLI linkage

Since I started looking into PowerShell and PowerCLI, I gathered a couple of links which I found interesting and useful. I needed a way for them to be accessible anytime anywhere. Obviously the first thing that came across my mind was putting them on my blog somewhere.

I decided to dedicate a page on my blog to PowerShell/PowerCLI. I arranged all my links into clear categories so they can easily be located. Hopefully you’ll find it useful as well.

If you’re new to PowerShell/PowerCLI, I recommended some good books on my page too. All these books are worth reading and will get you building your own scripts in no time! If you’re not a programmer and think writing scripts is not for you, please reconsider and find out how easy PowerShell/PowerCLI really is. PowerShell is Microsoft’s new scripting platform and management strategy, so if you’re a Windows admin you’ll have to face it sooner or later. It’s just a matter of time.

If you think I missed some good links worth the mention on my page, please let me know by dropping me an email, ping me on twitter or just leave a comment below.

PowerCLI: Get WMI info from isolated guests

A few weeks back I posted an article on matching Windows and VMware disks. Unfortunately this would work only if you could remotely query WMI information from that VM. If you have any VM that’s isolated or behind a firewall, you are out of luck. This bothered me, so I started looking for a uniform method to retrieve WMI information. I already knew that it was possible to run PowerShell scripts inside a guest using the Invoke-VMScript cmdlet, but unfortunately I don’t have PowerShell installed in all my VMs yet. When reading through the change log of PowerCLI 4.0 Update 1, I noticed the following enhancement of the Invoke-VMScript cmdlet:

feature Enhanced Invoke-VMScript to support BAT (Windows) and BASH (Linux) scripts.

When it’s possible to run BATCH scripts inside a guest, it’s probably possible to run executables directly too. So I took this for a test and it turned out that it was working indeed. View the following piece of code to execute the “dir c:\” command inside a VM.

Connect-VIServer vmwsv392

$VM = Get-VM ( Read-Host "Enter VM name" )
$ESXHost = $VM | Get-VMHost

$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", "", "")

Invoke-VMScript "dir c:\" -vm $VM -HostCredential $HostCred -GuestCredential $GuestCred -ScriptType "bat"

When running this script on my environment, I receive a nice directory listing of the c: drive on that VM. Nice!

Let’s take this method one step further. As of Windows 2003 there’s a wmi command-line utility available to us called “wmic.exe”. After fiddling around with all the available options of this command, I figured out a way to get WMI info in csv format. The syntax I need to provide me that information is:

wmic path <WMI_class> get <property_list> /format:csv

For example I can retrieve a list of diskdrives and their sizes using:

wmic path win32_diskdrive get caption,deviceid,size /format:csv

The next challenge I faced, was the fact that the info is returned as a string. I needed a way to convert the string value to an array, preferably an array of objects. All I was looking for was the output of the Import-Csv cmdlet, but unfortunately this cmdlet doesn’t accept data on the pipe. The solution I found to this is rather simple, just dump the string value to an intermediate temporary file and import that file using Import-Csv.

To do this properly we first have to cut off the first 2 characters of the string (There’s an extra carriage return and line feed character at the beginning) or else we can’t import the file using Import-Csv, because it expects the header to be on the first line.

I’ve modified the previous example code a bit as shown below:

Connect-VIServer vCenterServer01

$VM = Get-VM ( Read-Host "Enter VM name" )
$ESXHost = $VM | Get-VMHost

$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 caption,deviceid,size /format:csv" -vm $VM -HostCredential $HostCred -GuestCredential $GuestCred -ScriptType "bat"

$FileName = [System.IO.Path]::GetTempFileName()
$Out.Substring(2) > $FileName
$In = Import-Csv $FileName
Remove-Item $FileName

When you look at the output window, you clearly see the differences between the $out and $in objects.

The converted $in object can easily be used inside PowerShell scripts.
Imagine the possibilities!

Voted #29 top blogger on vSphere-land.com

In my previous post, I already wrote about the Top25 Bloggers that were announced by Eric Siebert on vSphere-land.com. Eric has now put the full voting results online. Out of the 66 blogs I ended up as 29th.

Although I didn’t make it into the Top25, I’m still very satisfied ending up on the 29th place with all that fierce competition around.

I would like to thank everyone for voting for me. I see this as a positive feedback and apparently my posts are interesting enough for people to include me in their personal top10. Thank You!

vSphere-land Top25 bloggers

The votes have been counted and the new Top25 bloggers are revealed by Eric Siebert on vSphere-land. A total amount of over 700 people from all over the world have casted their votes, which delivered Eric a nice weekend counting.

The new Top25 as published by Eric siebert on vSphere-land:

  1. Yellow Bricks – Duncan Epping – 158 #1 votes – total score of 4,191
  2. Virtual Geek – Chad Sakac – 111 #1 votes – total score of 2,938
  3. Scott Lowe’s Blog – Scott Lowe – 56 #1 votes – total score of 2,889
  4. NTPro.nl – Eric Sloof - 22 #1 votes – total score of 2062
  5. RTFM Education – Mike Laverick – 7 #1 votes – total score of 1,734
  6. Virtualization Evangelist – Jason Boche – 13 #1 votes – total score of 1,482
  7. VM/ETC – Rich Brambley – 5 #1 votes – total score of 1,138
  8. Gabe’s Virtual World – Gabrie van Zanten – 8 #1 votes – total score of 1,096
  9. Virtual Storage Guy – Vaughn Stewart – 58 #1 votes – total score of 990
  10. Virtu-Al – Alan Renouf – 18 #1 votes – total score of 831
  11. Virtualization Pro – Eric Siebert & Others – 3 #1 votes – total score of 774
  12. vCritical – Eric Gray – 15 #1 votes – total score of 738
  13. VMware Tips - Rick Scherer -  5 #1 votes – total score of 726
  14. Frank Denneman – Frank Denneman – 22 #1 votes – total score of 697
  15. The VM Guy – Dave Lawrence – 2 #1 votes – total score of 643
  16. Planet VM – Tom Howarth – 4 #1 votes – total score of 633
  17. The Slog – Simon Long – 8 #1 votes – total score of 614
  18. VMGuru.nl – Various – 18 #1 votes – total score of 569
  19. Mike D’s Virt. Blog – Mike DiPetrillo – 2 #1 votes – total score of 537
  20. Hypervizor – Hany Michael – 8 #1 votes – total score of 453
  21. Techhead – Simon Seagrave – 12 #1 votes – total score of 452
  22. vReference – Forbes Guthrie – 11 #1 votes – total score of 443
  23. Pivot Point – Scott Drummonds – 2 #1 votes – total score of 380
  24. Technodrone – Maish Saidel-Keesing – 3 #1 votes – total score of 378
  25. Chris Wolf – Chris Wolf – 0 #1 votes – total score of 375

Congratulations to all Top25 bloggers.

Critical 2009 last-minute ESX3.5 patches

I just noticed that VMware released a couple of critical ESX3.5 fixes on December 29th, shortly after releasing ESX3.5 Update5 on December 3rd. Wading through the patch details I stumbled upon some severe issues addressed by the ESX350-200912401-BG patch. I quote some issues that caught my eye: 

  • ESX hosts might get disconnected from VirtualCenter Server. This issue occurs when the ESX hosts are a part of DRS cluster and snapshots and VCB operations are performed on their virtual machines.
    Symptom
    The host agent on ESX hosts might stop responding to VI Client connections, VirtualCenter Server connection and internal or third-party SDK scripts or applications connections.
  • Enabling NTP service through VI Client or VirtualCenter might generate incorrect /etc/ntp.conf and /etc/ntp/step-tickers configuration files, and might cause the NTP service not to synchronize with the NTP Server. After applying this fix, the strings in ntp.conf and the step-tickers files in /etc/ntp/ are updated correctly.
  • Storage vMotion fails with the following error:
    Source detected that destination failed to resume.
    This occurs when performing storage vMotion of a virtual machine having at least two disks, of which one is RDM (located in the same folder as VMX), and the others are normal VMDK files in the destination VMFS volume. Both the RDM pointer and the normal VMDK file should have the same name for this issue to occur. The normal VMDK files are also deleted when storage vMotion fails.
    When the virtual machine is powered on the next time after this failure, the following error is displayed: Cannot open the disk.

Now that are issues that can get you in a really awkward position IMHO. Especially notice the yellow marked line, Ouch!. So take my advice and implement these patches a.s.a.p.

Support your favourite blog. Vote Now!

In case you didn’t noticed already, Eric Siebert  from vsphere-land has proclaimed a new top bloggers election. Blogging takes a lot of work, and most of us do this on top of our day jobs and hence don’t get paid for it. So I’m honoured to be a nominee alongside world’s greatest virtualization bloggers. Check out the nominees and if you read those various top blogs, please support your favourite ones and cast your vote. Eric even decided to expand the Top20 to the Top25, so there are 5 more rewards to be claimed.

As an added bonus there are great prices to win. Two randomly selected voters will receive a copy of the vSphere DVD training course from TrainSignal.

So what are you waiting for? VOTE!

In 2009, some of my more popular posts were:

Still here? VOTE!

Ofcourse I voted already to support my favourite ones, which was not an easy task, because there are so many great ones to choose from and to be honest, I don’t really have any favourites. I read lots of blogs on a daily basis and every blog has its own charms and characteristics. While some of them post on a daily basis and are a great source of news, others post less frequent, but deliver great quality in-depth articles. So I decided to pick the ones that really left a special impression on me over the last year, and surprisingly I find a lot of newcomers on my list.

Here’s my Top10:

  1. Arnim van Lieshout - Sorry guys, I just couldn’t resist :-D
  2. Yellow-Bricks – A blog with frequently lots of short quality articles both technical and news related, but also provides great quality in-depth articles. Sorry Duncan, no #1 vote for you :-)  As a multi-functional blogger and someone who’s always willing to reach out when someone is in trouble you get my second best vote.
  3. NTPro.nl – I guess by far the blog with the most posts over the last year. I just checked it and it were 524 posts to be exactly, which makes it an average of 1.4 a day!! Eric dude, where do you find the time. WOW! Now who can compete with Mr. Scoop on that?
  4. Virtu-Al – The mastermind behind the greatest TheVESI/PowerGui Powerpack ever. Great PowerCLI resource! Alan, this one is for you.
  5. Ken’s Virtual Reality – To be honoured for his vSwitch debate. Never saw such a huge quality multi-part post (8 parts!). Ken, you’ve got my vote!
  6. The SLOG – The man behind the vSphere practice exams and the VCP – and VCDX study notes, which helped me a lot prepping my VCP4 exam. Go Simon!
  7. Hypervizor – Good quality posts and not to forget his awesome Visio diagrams, which I consult very often. Definitely worth the vote. Hany, here you go!
  8. Frank Denneman – Provided great quality storage related posts, from which I learned a lot. Frank, Keep up the good work!
  9. Blog.scottlowe.org - Good series of quality articles, a great writer (love your books) and a huge apple fanatic. :-) Scott, sorry you finished 9th, but I think you don’t really need my vote to finish in the Top25 anyway and I just couldn’t let you out.
  10. Gabe’s Virtual World – Great blog with both quality articles and great reviews. Gabe, I hope you’re not offended, putting you on the sag wagon. On the other hand I’m certain you don’t have to rely on my vote to become top blogger again.

There are many more great blogs around that belong in the Top25, but you guys probably won’t need my vote anyway. So I hope I didn’t offend anyone, by not putting you on my list. But you see, I was only allowed to pick 10.

Hey dude! Are you still reading? VOTE! VOTE! VOTE!

How to force a login on a QLogic HBA

When running some storage test on an ESX 3.5 environment lately, I ran into a problem where a dead storage path disappeared after a rescan. While this was as expected, the storage path didn’t return after fixing it in the SAN and running a rescan again. After a reboot of the ESX server, the new paths were available again. When digging in deeper it turned out that whenever we changed the zoning on the SAN so that a new storage target came available to the ESX server, that target came available only after a reboot of the ESX server.

After some research I stumbled upon this VMware KB article: Configuring fibre switch so that ESX Server doesn’t require a reboot after a zone set change. This article described exactly the problem I encountered and explained that this was the result of RSCN events being suppressed by the SAN switches. Investigation revealed indeed that RSCN events were being suppressed by the SAN switches, as seen in the screenshot below.

To resolve this issue the following solution was given by the kb article:

To enable RSCN events, configure the Switch Operating Parameters so that the Suppress Zoning RSCN on Zone Set Activations is disabled.

 

As the solution was simple, just uncheck the option, I didn’t want to change this option right away as I was unaware of the impact on the SAN fabric. It also was not clear to me why that option was activated in the SAN design anyway.

When analyzing the differences between a regular rescan and a reboot, we came across the HBA login process. What if we could force a HBA login? First thing we came up with was to disconnect the fiber from the ESX server, but that was an impractical approach. Next thing was trying to disable/enable the SAN switch port to which an ESX server HBA was connected. While monitoring the /var/log/vmkernel log, we noticed the following message in the /var/log/vmkernel log when we enabled the SAN switch port: “Waiting for LIP to complete”. That’s an odd message because that message is normally seen only when using the arbitrated loop topology while we were using point-to-point topology, but at least it indicated that the HBA was trying to login. After this performing a rescan revealed the new storage target to us.

The reason why we saw the “Waiting for LIP to complete” message was probably because of the default setting of the connection type (2 – loop preferred, then point-to-point) in the QLogic HBA BIOS. With this default setting the QLogic HBA will try the arbitrated loop protocol first, hence the aforementioned message in the/var/log/vmkernel log.

I was still not satisfied with this solution, because I would need a SAN storage administrator and I had to investigate the SAN switch to find the port the ESX server’s HBA was connected to. This method was also very error prone, because disabling the wrong port would cause a disruption to another system. So I opted for another option, which was finding a way to force a HBA to login to the SAN fabric from within the ESX server console. When discussing my problem on Twitter I received some tips from Yellow-BricksDuncan Epping. He pointed me to a paragraph of the QLogic Fibre Channel Driver ReadMe.

9.7 How to Force a LIP
----------------------

The following NVRAM parameters must be set in order to perform the
LIP reset:

    o Enable Lip Reset
    o Enable Target Reset -- if the attached targets should be
                       also be reset

If both the above parameters are disabled, a Full Login LIP is
executed.

Execute the following command to initiate the LIP reset process:

    # echo "scsi-qlalip " > /proc/scsi/qla2300/<host_no>

Although we weren’t using the arbitrated loop topology, this was definitely something to try. When executing the aforementioned echo command, we saw the same behavior in the /var/log/vmkernel log as when we disabled/enabled the SAN switch port. After this the only thing left to do was performing a rescan of the HBA. This solution enabled me to reveal new SAN storage targets without an ESX server reboot.

The QLogic adapter BIOS settings in this environment were not set according to the Driver ReadMe above.  We tested this without changing the adapter BIOS settings and the table below shows the settings at the time of testing, which are the QLogic default.

Enable LIP Reset No
Enable LIP Full Login Yes
Enable Target Reset Yes

Summary

To resolve the problem, we need to deactivate the RSCN suppressing on the SAN switches, as describes by the VMware kb article.
Until than we have a workaround using the following ESX server console commands:

echo "scsi-qlalip" > /proc/scsi/qla2300/<host_no>
esxcfg-rescan vmhba<host_no>

where <host_no> must be replace with the vmhba number.

I don’t know if this method is supported or is causing disruptions on your vms, so test this thoroughly if you want to use these commands on your environment. I also don’t know if these commands still work if you force the connection topology to point-to-point only in the QLogic HBA BIOS.

Match VM and Windows harddisks using PowerCLI

Today I was asked to extend a disk of a Windows virtual machine. Normally this is a standard procedure and finished within minutes. The hardest part of the procedure is to check the scsi id from within Windows and match the Windows disk to the corresponding virtual disk in the virtual machine’s hardware settings. Unfortunately the vm in question today had only 26 virtual disks spread over 2 virtual SCSI controllers. Same procedure, although you need a little bit more time to figure things out.

When clicking my way through the Windows disk manager I noticed a strange phenomenon. Two of my Windows disks had the same scsi ids. Not only the same target id, but also the same Busnumber!. It turns out that the Busnumber doesn’t identify your SCSI controller, which  I was always thinking. After some digging in WMI, I found a SCSIPort property on the W32-DiskDrive WMI class. This property is the one that identifies the SCSI controller.

Oh boy, this daunting task is screaming to be scripted!. After a quick search in my administrators manual (google), I found a blog post from Hugo Peeters. His script uses the same WMI properties to match the Windows disk to its corresponding virtual disk, to calculate the freespace for each virtual disk. Taking advantage of this script I created the following script to create a mapping table between Windows disks and their corresponding virtual disks.

# This script requires PowerCLI 4.0 U1
#
# Create Disk Mapping Table
# 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= @()
$Vm = Read-Host "Enter VMName to create disk mapping for"

# 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}

if (($VmView = Get-View -ViewType VirtualMachine -Filter @{"Name" = $Vm})) {
    $WinDisks = Get-WmiObject -Class Win32_DiskDrive -ComputerName $VmView.Name
    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 "VM $Vm Not Found"}

Disconnect-VIServer * -Confirm:$false

The drawback of this script is that the user used to run the script must also have Windows administrator privileges on the vm you want to create a mapping table for and that you must be able to remotely query WMI on the vm. So this isn’t going to work out for all vms, e.g. DMZ, but maybe that’s something for a future version.

I recently made some improvements that get rid of these limitations. Read all about it in Match VM and Windows harddisks part 2.

If you have multiple vCenter servers, you don’t have to search which vCenter the vm is registered on, just enter all your vCenter servers to the $VCServerList. Ofcourse you need PowerCLI 4.0 U1 for this feature to work. :)

Update:

As requested in the comments, below is a sample output of this script:

VMDiskMapping

Update2:

Continue reading Match VM and Windows harddisks part 2 to read about the improvements I made.