Hi Folks
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?
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:
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
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:
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
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
I walked the registry path as well, some observations
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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
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:
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:
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
I love the way you code, it so articulate :smileygrin:
I see, thats ashame
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:
@Mike_Yazbeck
I just see the result on the picture you posted but not the script you generated it with Could you please post it here?
Thanks in advance!
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.
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...
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
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 :
Yes, I guess you are right in this case LucD I have never seen any working script that is consistently showing the correct result.
FMON Update: It looks like the serial number is just missing from Windows Server 2016. It shows up on our 2008 and 2012 servers.
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.
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"