VMware Cloud Community
amit_143
Contributor
Contributor

Power CLI script to find pcislotnumer(UI number) in a windows guest OS

Hi LucD,

I have a query from one of the customer who wants to get the following details from windows host running on VMware.

Customer uses different disk types for our VMs. R10, R5, AutoTiered and so on.

From the VMware environment they can see wich vmdk is on what type of disk.

Our challenge is to find, from within the guest OS, which physical disk is which vmdk.

As long as there is only 1 scsi card there is no problem.

We can match

$VM.Extensiondata.Config.hardware.device.UnitNumber in vmware

to

the "SCSI Target ID" in the guest OS.

(By running the following in the guest OS: get-wmiobject -class "Win32_DiskDrive" -namespace "root\CIMV2" -computername localhost) and then get the value of SCSITargetId.

UnitNumber = SCSITargetID

But if there are more than 1 scsi card we need to match the cards in vmware to the scsi cards in the guest OS somehow.

We've only found one way of doing this but we can't do it programmatically and that is what we need.

In VMware we can find the PCI slot number of a scsi card.

We filter

$VM.Extensiondata.Config.hardware.device on devices with deviceinfo.label "SCSI Controller" and then look at

$device.slotinfo.pcislotnumber.

We can match that value from vmware to the value in the guest OS(windows) by right clicking a physical disk in Disk manager and choosing properties.

The value "Location" in the General Tab always matches the pcislotnumber from vmware. 160 in the example below.

Example

Location: Location 160 (Bus Number 0, Target Id 1, LUN 0)

Also if we look under the Details tab and choose the property

"UI number" we find 160 but in HEX. A0

disk properties general.JPGDisk properties.JPG

We can't seem to find these properties in Windows by using windows native commands so we think that the VMwaredriver generates the information.

- How can we find the pcislotnumer(UI number) in a windows guest OS in a programatic way?

8 Replies
likeahoss
Enthusiast
Enthusiast

You may be looking for something like the Get-DiskSCSILun @ https://rvdnieuwendijk.com/2012/05/29/powershell-function-to-get-disk-scsi-lun-number/

After loading that function, I performed this one-liner:

(get-vm).Guest | ?{$_.OSFullName -like "*Windows*" -and $_.State -eq "Running"} | Select -expand VMName | Get-DiskScsiLun | ft -a


Which resulted in listing all the running Windows VM's info you're looking for.  This is my home lab, and I truncated some data, but you get the point.


SCSIBus SCSITargetId SCSIPort Computer    SCSILogicalUnit DeviceID

------- ------------ -------- --------    --------------- --------

      0            0        2 computer1                     0 C:

      0            0        2 computer2                     0 C:

      0            1        2 computer3                     0 C:

Hackim
Contributor
Contributor

Hi and thank you,

I'm the customer Smiley Happy

The problem I'm trying to solve is to match "SCSIPort" in the guestOS to "SCSIBusId" on the VMware side.

Using "SCSIPort" doesn't work if you have a VM with more than one controller.

Well It seems to work sometimes but it all depends on what type of controllers you have.

In some cases there is a match, scsicontroller 0 in VMware also has SCSIPort 0 in the guestOS.

But there is often an offset.


Scsicontroller 0 in VMware sometimes has SCSIPort 2 and in other cases SCSIPort 1 in the guestOS.

The offset isn't consistent, in some VMs it's +1 and in others it can be +2 or 0 offset.

You can't rely on SCSIPort to make the match.


As you can see in your own example,

your controllers has SCSIPort 2 in the guestOS.

I guess that it is scsicontroller 0 in VMware.

The only way I've found so far is using PCISlotnumer as the key to match, since it seems to be consistent on all the VMs that I've tried so far.

Regards,

Hackim

0 Kudos
LucD
Leadership
Leadership

I have to agree, the function will not cover all possible configurations (multiple controllers, different type controllers...).

I have been playing with the UINumber (or Location) as well.

The only valid way seems to be to scan the registry (which limits this to VMs with a Windows guest OS).

This is what I'm currently using

$regPCI = 'HKLM:\System\CurrentControlSet\Enum\PCI\'

$regSCSI = 'HKLM:\System\CurrentControlSet\Enum\SCSI\'

$TargetControllers = 'LSI_SAS'

Get-ChildItem -Path $regPCI | %{

    foreach($scsiCtrl in (Get-ChildItem -Path $_.PSPath)){

        foreach($tgtCtrl in (Get-ItemProperty -Path $scsiCtrl.PSPath | where{$TargetControllers -contains $_.Service})){

            Get-ChildItem -Path $regSCSI | %{

                foreach($scsiDev in (Get-ChildItem -Path $_.PSPath)){

                    foreach($tgtScsiDev in (Get-ItemProperty -Path $scsiDev.PSPath | where{$_.Service -eq 'disk' -and $_.ContainerID -eq $tgtCtrl.ContainerID})){

                        $tgtScsiDev | select @{N='Service';E={$tgtCtrl.Service}},@{N='UINumber';E={$tgtCtrl.UINumber}},LocationInformation

                    }

                }

            }

        }   

    }

}

When I run this againsta VM with 3 controllers and 4 vDisks, I get the below output.

Notice that there are disks in there, the were removed (for the controller under UInumber 160).

Andthere are some "special" situations in the UInumber as well.

I noticed that the normal step value of 32 between successive controllers is not always valid.

I suspect this has to do with the history (controllers add/removed,type changed...)

Notice for example the sequence 160,192,256 in the following run (224 is missing)

Service UINumber LocationInformation            

------- -------- -------------------            

LSI_SAS      161 Bus Number 0, Target Id 5, LUN 0

LSI_SAS      160 Bus Number 0, Target Id 0, LUN 0

LSI_SAS      160 Bus Number 0, Target Id 1, LUN 0

LSI_SAS      160 Bus Number 0, Target Id 2, LUN 0

LSI_SAS      160 Bus Number 0, Target Id 3, LUN 0

LSI_SAS      160 Bus Number 0, Target Id 4, LUN 0

LSI_SAS      256 Bus Number 0, Target Id 0, LUN 0

LSI_SAS      192 Bus Number 0, Target Id 1, LUN 0

The actual function to do the automatic mapping isn't ready yet. Too many unclear situations, which I can't seem to be able to analyse automatically.

I consider this a "work in progress"


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

amit_143
Contributor
Contributor

Thanks Lucd for your efforts

0 Kudos
Hackim
Contributor
Contributor

Thank you very much Luc.

This will certainly help alot!

I've seen a lot of blog post regarding matching disks but none of them seemed to solve the whole problem.

That's why I've tried this approach instead.

Thanks to your example, my approach using UINumber might be usable by a lot of people.

I'll dig deeper.

Now that I can do this programmatically I can test it on thousands of VMs to see if the results are consistent.

LucD
Leadership
Leadership

You're welcome.

I'm trying out the following rules:

  • The UInumber needs to be sorted, the 1st corresponds with Bus 0, 2nd with bus 1...
  • The targetId in the registry seems to correspond with the unitnumber in the vSphere SCSIid. I.e. (0,3)  on a Hard disk should have target 3 in the registry
  • The Bus and Lun numbers in the registry are useless

I will also need to check if the rules hold for all types of SCSI controllers, and all Windows flavours.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

stephenrbarry
Enthusiast
Enthusiast

I'm so glad I found this, I've been trying to figure out a way to discover the "UI number" through PowerShell for almost a year due to all the issues mentioned with other methods of correlating disks.  I realize this is an old post, but I was curious to hear whether you all have had success with this method?

0 Kudos
LucD
Leadership
Leadership

Not really, I can't seem to detect any logic in the numbering system used.

Which confirms my claim that there is no fool-proof method to correlate the VDMK with the guest OS partitions.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos