VMware Cloud Community
Mike_Yazbeck
Enthusiast
Enthusiast
Jump to solution

Matching VM Disks to Windows Disk for SCSI Controller 1 (scripts online always work for controller 0)

Hi Folks Smiley Happy

I am looking to get to the bottom to the bottom of matching VMWare hard disks to disks in Windows using WMI.

So far all scripts I have found work with SCSI Controller 0, but it fails when trying to get details on SCSI Controller 1 and for some reason the details in WMI - it always incorrectly reports it as controller 0 even when its not.

I found this article which is great, but surely there is a Windows WMI way to get this to compare?

echo( "hello wordl" 😞 Match virtual hard disks in Virtual Center with their disk labels in Windows ...

The other thing I was wondering was based on the article above, is it possible to get the location of the VMX file and read its contents into a variable so that you can match the "scsi1.pciSlotNumber" value to the number reported in WMI?

I have scoured the net and this is the closest thing I can find to unpicking this issue.

Any help would be greatly appreciated :smileygrin:

1 Solution

Accepted Solutions
Mike_Yazbeck
Enthusiast
Enthusiast
Jump to solution

This is roughly how my code looks:

[Int64]$HKLM = "2147483650"

[String]$value = "UINumber"

$Reg_Query = Get-WmiObject -List "StdRegProv" -Namespace root\cimv2 -Computername $server -Credential $cred

ForEach ($LogicalDisk in $Win32_LogicalDisk)

{

    $LogicalDiskToPartition = $Win32_LogicalDiskToPartition | Where-Object {$_.Dependent -eq $LogicalDisk.Path}

    if ($LogicalDiskToPartition)

    {

        $DiskDriveToDiskPartition = $Win32_DiskDriveToDiskPartition | Where-Object {$_.Dependent -eq $LogicalDiskToPartition.Antecedent}

        if ($DiskDriveToDiskPartition)

        {

            $DiskDrive = $Win32_DiskDrive | Where-Object {$_.__Path -eq $DiskDriveToDiskPartition.Antecedent}

            if ($DiskDrive)

            {

                $WMI_VirtualDisk = "" | Select DeviceID, SCSIBus, SCSITargetId, Size, WinDisk, VolumeName

                $WMI_VirtualDisk.DeviceID = $LogicalDisk.DeviceID

                #$WMI_VirtualDisk.SCSIBus = $DiskDrive.SCSIBus 'Technically it does work, but only for SCSI controller 0

                $WMI_VirtualDisk.SCSITargetId = $DiskDrive.SCSITargetId

                $WMI_VirtualDisk.Size = [Math]::Round($DiskDrive.Size / 1GB)

                $WMI_VirtualDisk.WinDisk = $DiskDrive.Index

                $WMI_VirtualDisk.VolumeName = $LogicalDisk.VolumeName

               

                #new code - works!

                $PNPDeviceID = $DiskDrive.PNPDeviceID.Split("\")

                $key = "SYSTEM\CurrentControlSet\Enum\$($PNPDeviceID[0])\$($PNPDeviceID[1])\$($PNPDeviceID[2])"

                $SCSI_Controller = ($Reg_Query.GetDWORDValue($HKLM,$key,$value)).uvalue

                Switch ($SCSI_Controller)

                {

                     "32" {$SCSI_Controller = '1';Break}

                    "160" {$SCSI_Controller = '0';Break}

                    "256" {$SCSI_Controller = '1';Break}

                    "161" {$SCSI_Controller = '2';Break}

                    "224" {$SCSI_Controller = '3';Break}

                  Default {$SCSI_Controller = '0';Break}

                }

                $WMI_VirtualDisk.SCSIBus = $SCSI_Controller

                $WMI_DiskArray += $WMI_VirtualDisk

            }

        }

    }

}

Where I work we use a NetApp SAN solution. I dont think that that matters all too much, but I thought I would give you a heads up as you are likely to be using something very different Smiley Happy

The $PNPDeviceID is a property of the $DiskDrive which essentially appears to be a registry key path which if you split, you can access the registry remotely using WMI, which works like a charm :smileygrin:

I literally just got this finished and working the way I want... hope it helps :smileygrin:

View solution in original post

16 Replies
LucD
Leadership
Leadership
Jump to solution

This has been my Holy Grail since years :smileygrin:

And believe me, the author of that post is a bit optimistic with his claim of "foolproof" I'm afraid.

For example, try removing/adding hard disks, and this Location number will change, and with no logic to be detected so far.

I still give my quest an occasional try, but I just don't seem to be making any progress :smileycry:

As a side-note, foolproof in my book, also means that the logic shall also work for VMs that run a Linux guest OS.

But I keep trying to find a method.

Perhaps one day the light will shine :smileycool:


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

Mike_Yazbeck
Enthusiast
Enthusiast
Jump to solution

I can imagine :smileygrin:

I think I have managed to suss it out.

Although the author you are talking about that claimed his script was "fool proof" (which clearly isnt), he was actually on the right track.

The solution is in fact a registry key! I will send some screenshots to explain tomorrow :smileygrin:

One of the main WMI properties for the disk drive is just a registry tree which can be broken down using "split".

Hopefully when I get it all working, I can demonstrate :smileygrin:

Watch this space Smiley Wink

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I walked the registry path as well, some observations

  • although you can find the number in there, there is no apparent logic to map the disk label to the number
  • by definition doesn't cover VMs that run a Linux guest OS


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

Reply
0 Kudos
Mike_Yazbeck
Enthusiast
Enthusiast
Jump to solution

This is roughly how my code looks:

[Int64]$HKLM = "2147483650"

[String]$value = "UINumber"

$Reg_Query = Get-WmiObject -List "StdRegProv" -Namespace root\cimv2 -Computername $server -Credential $cred

ForEach ($LogicalDisk in $Win32_LogicalDisk)

{

    $LogicalDiskToPartition = $Win32_LogicalDiskToPartition | Where-Object {$_.Dependent -eq $LogicalDisk.Path}

    if ($LogicalDiskToPartition)

    {

        $DiskDriveToDiskPartition = $Win32_DiskDriveToDiskPartition | Where-Object {$_.Dependent -eq $LogicalDiskToPartition.Antecedent}

        if ($DiskDriveToDiskPartition)

        {

            $DiskDrive = $Win32_DiskDrive | Where-Object {$_.__Path -eq $DiskDriveToDiskPartition.Antecedent}

            if ($DiskDrive)

            {

                $WMI_VirtualDisk = "" | Select DeviceID, SCSIBus, SCSITargetId, Size, WinDisk, VolumeName

                $WMI_VirtualDisk.DeviceID = $LogicalDisk.DeviceID

                #$WMI_VirtualDisk.SCSIBus = $DiskDrive.SCSIBus 'Technically it does work, but only for SCSI controller 0

                $WMI_VirtualDisk.SCSITargetId = $DiskDrive.SCSITargetId

                $WMI_VirtualDisk.Size = [Math]::Round($DiskDrive.Size / 1GB)

                $WMI_VirtualDisk.WinDisk = $DiskDrive.Index

                $WMI_VirtualDisk.VolumeName = $LogicalDisk.VolumeName

               

                #new code - works!

                $PNPDeviceID = $DiskDrive.PNPDeviceID.Split("\")

                $key = "SYSTEM\CurrentControlSet\Enum\$($PNPDeviceID[0])\$($PNPDeviceID[1])\$($PNPDeviceID[2])"

                $SCSI_Controller = ($Reg_Query.GetDWORDValue($HKLM,$key,$value)).uvalue

                Switch ($SCSI_Controller)

                {

                     "32" {$SCSI_Controller = '1';Break}

                    "160" {$SCSI_Controller = '0';Break}

                    "256" {$SCSI_Controller = '1';Break}

                    "161" {$SCSI_Controller = '2';Break}

                    "224" {$SCSI_Controller = '3';Break}

                  Default {$SCSI_Controller = '0';Break}

                }

                $WMI_VirtualDisk.SCSIBus = $SCSI_Controller

                $WMI_DiskArray += $WMI_VirtualDisk

            }

        }

    }

}

Where I work we use a NetApp SAN solution. I dont think that that matters all too much, but I thought I would give you a heads up as you are likely to be using something very different Smiley Happy

The $PNPDeviceID is a property of the $DiskDrive which essentially appears to be a registry key path which if you split, you can access the registry remotely using WMI, which works like a charm :smileygrin:

I literally just got this finished and working the way I want... hope it helps :smileygrin:

Mike_Yazbeck
Enthusiast
Enthusiast
Jump to solution

By the way, I would like to add this is coded with Windows in mind not Linux.

My script runs a menu system so that I can perform multiple functions independently.

Personally I recommend doing that here, and then calling a function from the menu that is specifically designed to talk to Windows and coding a separate function that talks to Linux :smileygrin:

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I was doing something similar at one point, see  3.  Re: Power CLI script to find  pcislotnumer(UI number) in a windows guest OS

But I stumbled on the fact that I couldn't find any logic in the numbers that you get.

When you start adding/removing SCSI controllers, the number, which you covered by the Switch, can be all over the place.

But if it works for, good find!


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

Mike_Yazbeck
Enthusiast
Enthusiast
Jump to solution

I love the way you code, it so articulate :smileygrin:

I see, thats ashame Smiley Sad

I've run my script against a couple servers and it seems to work - one of them was the primary exchange server and the other is clustered SQL server:

pastedImage_3.png

Reply
0 Kudos
WhiteCase
Contributor
Contributor
Jump to solution

@Mike_Yazbeck

I just see the result on the picture you posted but not the script you generated it with Smiley Happy Could you please post it here?

Thanks in advance!

Reply
0 Kudos
FMON
Enthusiast
Enthusiast
Jump to solution

Did you see my post from a couple days ago?  Hopefully this is what you've been looking for.  How to trace a VM disk to a guest disk.


It describes a method to perform this trace that is more reliable than referencing scsibus and scsitargetid.  The method should work irrespective of guest OS.  PowerShell code for Windows included.

Briefly:  for disks that are not physical mode RDM, match VMware disk uuid to serial number of disk in guest.  For physical mode RDM disks, match ScsiCanonicalName to serial number of disk in guest (perhaps with some ASCII to HEX conversion as required in my environment built on NetApp).

Not saying this is foolproof but if you find a place where this doesn't work I'd like to hear about it.

AlbertWT
Virtuoso
Virtuoso
Jump to solution

LucD

What about combining the PowerShell from this website: https://4sysops.com/archives/map-vmware-virtual-disks-and-windows-drive-volumes-with-a-powershell-sc...

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I have seen that method before, but found out that it doesn't work when the controllers and disks have been manipulated after the creation of the VM.

The IDs assigned to the controllers do not seem to follow a logic (that I know of).


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

jamesl73
Contributor
Contributor
Jump to solution

FMON​ I went to test your SerialNumber method and found that the WMI value is empty on all the VMs that I tested on, and they are not RDMs.  Any thoughts?

ConfigManagerErrorCode      : 0

LastErrorCode               :

NeedsCleaning               :

Status                      : OK

DeviceID                    : \\.\PHYSICALDRIVE1

StatusInfo                  :

Partitions                  : 1

BytesPerSector              : 512

ConfigManagerUserConfig     : False

DefaultBlockSize            :

Index                       : 1

InstallDate                 :

InterfaceType               : SCSI

MaxBlockSize                :

MaxMediaSize                :

MinBlockSize                :

NumberOfMediaSupported      :

SectorsPerTrack             : 63

Size                        : 53686402560

TotalCylinders              : 6527

TotalHeads                  : 255

TotalSectors                : 104856255

TotalTracks                 : 1664385

TracksPerCylinder           : 255

__GENUS                     : 2

__CLASS                     : Win32_DiskDrive

__SUPERCLASS                : CIM_DiskDrive

__DYNASTY                   : CIM_ManagedSystemElement

__RELPATH                   : Win32_DiskDrive.DeviceID="\\\\.\\PHYSICALDRIVE1"

__PROPERTY_COUNT            : 51

__DERIVATION                : {CIM_DiskDrive, CIM_MediaAccessDevice, CIM_LogicalDevice, CIM_LogicalElement...}

__SERVER                    : Server21

__NAMESPACE                 : root\cimv2

__PATH                      : \\Server21\root\cimv2:Win32_DiskDrive.DeviceID="\\\\.\\PHYSICALDRIVE1"

Availability                :

Capabilities                : {3, 4}

CapabilityDescriptions      : {Random Access, Supports Writing}

Caption                     : VMware Virtual disk SCSI Disk Device

CompressionMethod           :

CreationClassName           : Win32_DiskDrive

Description                 : Disk drive

ErrorCleared                :

ErrorDescription            :

ErrorMethodology            :

FirmwareRevision            : 1.0

Manufacturer                : (Standard disk drives)

MediaLoaded                 : True

MediaType                   : Fixed hard disk media

Model                       : VMware Virtual disk SCSI Disk Device

Name                        : \\.\PHYSICALDRIVE1

PNPDeviceID                 : SCSI\DISK&VEN_VMWARE&PROD_VIRTUAL_DISK\4&3B5019BE&0&000100

PowerManagementCapabilities :

PowerManagementSupported    :

SCSIBus                     : 0

SCSILogicalUnit             : 0

SCSIPort                    : 2

SCSITargetId                : 1

SerialNumber                :

Signature                   :

SystemCreationClassName     : Win32_ComputerSystem

SystemName                  : Server21

Scope                       : System.Management.ManagementScope

Path                        : \\Server21\root\cimv2:Win32_DiskDrive.DeviceID="\\\\.\\PHYSICALDRIVE1"

Options                     : System.Management.ObjectGetOptions

ClassPath                   : \\Server21\root\cimv2:Win32_DiskDrive

Properties                  : {Availability, BytesPerSector, Capabilities, CapabilityDescriptions...}

SystemProperties            : {__GENUS, __CLASS, __SUPERCLASS, __DYNASTY...}

Qualifiers                  : {dynamic, Locale, provider, UUID}

Site                        :

Container                   :

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso
Jump to solution

Yes, I guess you are right in this case LucD​ I have never seen any working script that is consistently showing the correct result.

/* Please feel free to provide any comments or input you may have. */
jamesl73
Contributor
Contributor
Jump to solution

FMON​  Update:  It looks like the serial number is just missing from Windows Server 2016.  It shows up on our 2008 and 2012 servers.

Reply
0 Kudos
GabCava
Enthusiast
Enthusiast
Jump to solution

sorry Mike.. some time has passed but...you said you ran the script against those servers, but I guess from what I see you run the script from within the OS right? So you need Windows admin credentials. I'm a VMware admin but not OS admin.. Arnim Van Lieshout already considered this a while ago but his script worked only for vSCSI 0.

Reply
0 Kudos
jamesl73
Contributor
Contributor
Jump to solution

I found that for some reason our automation for Windows Server 2016 was somehow missing a setting in the .vmx file.  After updating the .vmx with the below parameter we are able to get the serial number from WMI.

disk.EnableUUID = "TRUE"

Reply
0 Kudos