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.

Related posts:

  1. Setting custom attributes with VMware PowerCLI Tweet Last week I wanted to extend my vCenter with some extra custom attributes on my VMs. This would extend the usability of the Export List feature for reporting purposes....
  2. How big is my VM? Tweet If you want to know the size of your vm, you probably first look at the size of the virtual disks in the vm’s settings, but there’s more to...
  3. List HBA WWPNs and LUNs using Powershell Tweet Lately I’m moving around my VMs and storage luns between my ESX clusters a lot to accomplish a complete redesign of my Virtual Infrastructure. At some point I got...
  4. Bulk change your ESX root password Tweet Have you ever been facing your security department demanding you to change your ESX root password? Well I did. At the current site there’s a strict security policy where...
  5. PowerCLI 4.0 Update 1- Another leap forward Tweet Last week VMware released PowerCLI 4.0 Update1. According to the PowerCLI blog this new version contains over 60 new cmdlets as well as greatly improved performance. One great thing...

11 Comments on “Match VM and Windows harddisks using PowerCLI”

  1. #1 Hugo Peeters
    on Dec 22nd, 2009 at 10:14 am

    Cool stuff!

  2. #2 dmVI
    on Jan 6th, 2010 at 3:09 am

    Can you post a sample of the output that you receive when running your script?

  3. #3 Arnim van Lieshout
    on Jan 10th, 2010 at 5:03 pm

    Hi dmVI,

    I’ve updated my post with a sample output.

  4. #4 PowerCLI: Get WMI info from isolated guests | Arnim van Lieshout
    on Jan 21st, 2010 at 10:04 am

    [...] isolated guests Jan 21st, 2010 by Arnim van Lieshout. 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 [...]

  5. #5 Match VM and Windows harddisks using PowerShell - part 2 | Arnim van Lieshout
    on Feb 3rd, 2010 at 10:02 am

    [...] 3rd, 2010 by Arnim van Lieshout. 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 [...]

  6. #6 Jay
    on Jan 17th, 2012 at 4:39 am

    I’ve been playing with this script and it fails to map any Windows drives, just returns “No matching Windows disk found for SCSI id 0 : 0″ etc.

    I’m a newbie to scripting so woudl appreciate any help here.
    I have vCentre 4.1U2 and PowerCLI 4.1.1 on Windows 2008 R2

    I can remote query the disk details with wmi/powercli with the following script no prob….

    # $diskdrive – harddisk related info
    # $diskpartition – partition related info
    # $Logicaldrive – Drive related info
    $Srv = Read-Host “Enter Name to list disk details for”

    $diskdrives = Get-WmiObject win32_diskdrive -ComputerName $Srv

    foreach($diskdrive in $diskdrives){
    Write-Host “———————————————————”
    Write-Host “Disk:” $diskdrive.Index “`n SCSI:” $diskdrive.SCSIBUS “`n SCSITargetID:” $diskdrive.SCSITargetID “`n SCSILU:SCSILogicalUnit”
    foreach($diskpartition in $diskdrive.getrelated(“win32_diskpartition”)){
    Write-Host “Disk Partition:” $diskpartition.NAME
    FOREACH($LOGICALDRIVE IN $diskpartition.getrelated(“win32_logicaldisk”)){
    write-host “Logical drive:” $LOGICALDRIVE.name
    }
    }

    }

  7. #7 Arnim van Lieshout
    on Jan 30th, 2012 at 10:59 pm

    Hi Jay,

    Might be related to Windows 2008 R2. There is an updated version of this function available in our book: VMware vSphere PowerCLI Reference: Automating vSphere Administration. Look for listing 7.4; the code is available for download from the Wiley site.

  8. #8 Dreamer
    on Feb 3rd, 2012 at 10:44 pm

    Hi,

    Thanks for the script. This is exactly what I am looking for.

    So basically the $windisk.scsiport -1 is to identify the scsi controller.

    However, in my environmnet its not exactly matching.

    For all the 4 scsi controllers the bus numbers are 0, 1, 2, 3 respectively.

    And the port numbers for the disks which are attached to these controllers (0, 1, 2, 3) are (2, 5, 4, 3).

    So the logic to map doesnt work.

    Am i missing something?

    Thanks for the help.

    Regards,
    Naresh

  9. #9 Arnim van Lieshout
    on Feb 14th, 2012 at 1:25 pm

    There’s an updated version available from our PowerCLI book.
    The scripts are available for download from the Wiley site.

  10. #10 Christina Sharp
    on Jun 5th, 2012 at 11:09 pm

    Is there any way to identify mapping to mountpoints?

  11. #11 Christina Sharp
    on Jun 6th, 2012 at 12:06 am

    Actually my bad… the mountpoints in question weren’t showing up because they were in a different SCSI Controller. Everything for SCSI Controller 0 reported perfectly but anything in SCSI Controller 1 didn’t return any windows disk information.

Leave a Comment