PowerCLI

 View Only
Expand all | Collapse all

Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

glwnieves

glwnievesNov 24, 2020 04:28 PM

LucD

LucDNov 24, 2020 08:23 PM

  • 1.  Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 23, 2020 09:53 PM

    Hey Guys,

    So, I'm not that great at scripting put I'm pretty resourceful in finding the appropriate scripts for things I need. I am having an issue though. So I found a script that will Pull the Disk/UUID Information from VMware and from a Windows machine and then match the VMware Disk configuration to the Windows Disk Configuration.

    Here is the script I am using for that:

     Running this produces a result like this:

    glwnieves_0-1606167813748.png

    I was then asked to also include the VMware SCSI information. I found another script that does that.

     

     That produces the following result:

    glwnieves_1-1606167913908.png

     

    So I have two questions really.

    1. Can someone help me combine both scripts into one?

    2. Can someone also help me figure out how to have this script run against a list of machines and export it to a CSV File? The output can either be one file or separate files per VM. I'm okay with either.

    I was thinking maybe the script can reference a .txt or csv file that I populate with all of the machines but I'll defer to whatever you guys recommend. The only issue I see there is since you have to define the VM Name and the DNS Name (Windows WMI Portion of the script) I'm not sure how I can do both with one txt input file.

    I have about 50 machines I have to run this against and just looking for the easiest way to accomplish this. At a minimum if someone can help be combine both scripts into one that would be awesome. Thanks guys, I appreciate the help! 



  • 2.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 07:49 AM

    First, let me start with a word of warning that I always give when I see a question to map Guest OS disks to VM's VMDK files.

    There is no fool-proof way to make that mapping.
    There are so many exceptions that there is no general rule that works.
    And I didn't even start about the mapping in Linux Guest OS.

    On the other hand, when certain conditions are met, you might be able to pull it off.
    If there is only one Guest OS partition/disk per VMDK.
    If there hasn't been any removal/addition of Guest OS partitions and/or VMDK since the creation of the VM.
    And a few other prerequisites.

    In your case (environment) all the conditions seem to be met.
    Then it would be a matter of mapping the SCSI controller to the VMDK and the VMDK to the Guest OS drive/partition.

    Is my assumption correct?



  • 3.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 01:35 PM

    Yes, your assumptions are correct. There is only one Windows partition per VMDK. Also, the number of Guest OS partitions/VMDKs have been the same since the creation of the VM.

     

    These servers are used for a specific purpose and that configuration shouldn't have changed since the creation of the VM. So far in all of my tests when I manually went to match up the result it has been accurate thus far. There should be a single standard across all of them.

     

    The only reason to run this script is to confirm that they all conform to the same standard. Anything that produces a different/odd result will require us to investigate it anyway. Thanks again for your help.



  • 4.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration
    Best Answer

    Posted Nov 24, 2020 02:25 PM

    Since all your VMs are meeting the specific requirements, you could try something like this

     

    # User with permission to query the WMI on the guest
    $user = 'domain\user'
    $pswd = 'VMware1!'
    $cred = New-Object -TypeName PSCredential -Argumentlist $user,(ConvertTo-SecureString -String $pswd -AsPlainText -Force) 
    
    # CSV file with a column named vmName
    Import-Csv -Path .\vmnames.csv -UseCulture -PipelineVariable row |
    ForEach-Object -Process {
        $vm = Get-VM -Name $row.vmName
    
        # If the script can't determine the FQDN of the Guest OS, the VM is skipped
        $winHostName = ''
        if($vm.Guest.State -eq 'Running'){
            if($vm.Guest.HostName -ne ''){
                $WinHostName = $vm.Guest.HostName
            }
            elseif($vm.Guest.IPAddress){
                $resolve = Resolve-DnsName -Name $vm.guest.IPAddress[0]
                if($resolve){
                    $WinHostName = $resolve.NameHost
                }
            }
        }
        if($winHostName){
            $vmDisks = Get-HardDisk -VM $vm | Sort-Object -Property Name
            $vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View
            $virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager
    
            # Getting the list of Windows disks and partitions using WMI
            $winDisk = Get-WmiObject -Class Win32_DiskDrive -ComputerName $WinHostName -Credential $cred
            $diskToDriveVolume = Get-WmiObject Win32_DiskDrive -ComputerName $WinHostName -Credential $cred| % {
                $disk = $_
                $partitions = "ASSOCIATORS OF " +
                    "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +
                    "WHERE AssocClass = Win32_DiskDriveToDiskPartition"
                Get-WmiObject -Query $partitions -ComputerName $WinHostName -Credential $cred| % {
                    $partition = $_
                    $drives = "ASSOCIATORS OF " +
                        "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +
                        "WHERE AssocClass = Win32_LogicalDiskToPartition"
                    Get-WmiObject -Query $drives -ComputerName $WinHostName -Credential $cred| % {
                        New-Object -Type PSCustomObject -Property @{
                            Disk = $disk.DeviceID
                            DriveLetter = $_.DeviceID
                            VolumeName = $_.VolumeName
                        }
                    }
                }
            }
            #Getting a disk serial number
            foreach ($disk in $winDisk)
            {
                $disk | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null
                $diskSerialNumber = $disk.SerialNumber
                if ($disk.Model -notmatch 'VMware Virtual disk SCSI Disk Device')
                {
                    if ($diskSerialNumber -match '^\S{12}$'){$diskSerialNumber = ($diskSerialNumber | foreach {[byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} } ) -join ''}
                    $disk.AltSerialNumber = $diskSerialNumber
                }
            }
            #Searching all VM disks and matching them with Windows disks by their SerialNumber / UUID
            foreach ($vmDisk in $vmDisks)
            {
                $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')}
                $windowsDisk = $winDisk | where {$_.SerialNumber -eq $vmDiskUuid}
                if (-not $windowsDisk){
                    $windowsDisk = $winDisk | where {$_.AltSerialNumber -eq $vmDisk.ScsiCanonicalName.substring(12,24)}
                }
                $ctrl = $vm.ExtensionData.Config.Hardware.Device | where{$_.Key -eq $vmDisk.ExtensionData.ControllerKey}
                $curDiskMap = "" | select vmDiskDatastore, vmDiskVmdk, SCSIAddress, vmDiskName, windowsDiskIndex, vmDiskUuid, windowsDeviceID, drives, volumes
                $driveVolumes = $diskToDriveVolume | where {$_.Disk -eq $windowsDisk.DeviceID}
                New-Object -TypeName PSObject -Property ([ordered]@{
                    VM = $vm.Name
                    vmDiskDatastore = $vmDisk.filename.split(']')[0].split('[')[1]
                    vmDiskVmdk = $vmDisk.filename.split(']')[1].trim()
                    SCSIAddress = "SCSI($($vmDisk.ExtensionData.UnitNumber):$($ctrl.BusNumber))" 
                    vmDiskName = $vmDisk.Name
                    windowsDiskIndex = if ($windowsDisk){$windowsDisk.Index}else{"FAILED TO MATCH"}
                    vmDiskUuid = $vmDiskUuid
                    windowsDeviceID = if ($windowsDisk){$windowsDisk.DeviceID}else{"FAILED TO MATCH"}
                    drives = $driveVolumes.DriveLetter
                    volumes = $driveVolumes.VolumeName
                })
            }
        }
        else{
            Write-Host "Could not determine FQDN for VM ($vm.Name)"
        }
    } | Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture

     



  • 5.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 03:26 PM

    So I modified the $user and $pswd values with the appropriate credentials. I created a vmware.csv file in the same directory that this script resides. I created a column "vmName" and I put one of the servers I want to run it against in that column.

    Snag_193d3536.png

     

     

    I received the following errors from PowerShell:

     

     

     

    Get-VM : 11/24/2020 9:49:34 AM Get-VM VM with name 'vEng' was not found using the specified filter(s). 
    At line:27 char:29
    + $vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | G ...
    + ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
    + FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM
    
    Exception calling "QueryVirtualDiskUuid" with "2" argument(s): "A specified parameter was not correct: dc"
    At line:65 char:13
    + $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($v ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException
    
    Exception calling "QueryVirtualDiskUuid" with "2" argument(s): "A specified parameter was not correct: dc"
    At line:65 char:13
    + $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($v ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException
    
    Exception calling "QueryVirtualDiskUuid" with "2" argument(s): "A specified parameter was not correct: dc"
    At line:65 char:13
    + $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($v ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException
    
    Exception calling "QueryVirtualDiskUuid" with "2" argument(s): "A specified parameter was not correct: dc"
    At line:65 char:13
    + $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($v ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException
    
    Exception calling "QueryVirtualDiskUuid" with "2" argument(s): "A specified parameter was not correct: dc"
    At line:65 char:13
    + $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($v ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException
    
    Exception calling "QueryVirtualDiskUuid" with "2" argument(s): "A specified parameter was not correct: dc"
    At line:65 char:13
    + $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($v ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException
    
    Exception calling "QueryVirtualDiskUuid" with "2" argument(s): "A specified parameter was not correct: dc"
    At line:65 char:13
    + $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($v ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException

     

     

     

    I looked and found the vEng value in the script but not sure if I'm supposed to change this value.

     

     

    glwnieves_2-1606230595645.png

     

    Also, I'm not sure if the errors caused this but the output mapped all of the Windows Drive letters to the same Uuid.

    glwnieves_4-1606231018961.png

     

    However, when I run the original script I used without the SCSI controller information it maps correctly.

     
     
     

    Snag_19348dc2.png

     

    What am I missing?

     



  • 6.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 03:33 PM

    I forgot to remove a test line from the script.
    Hence the error you got.
    I updated the code



  • 7.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 04:28 PM

    That fixed it. Thanks so much!!!



  • 8.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 06:16 PM

     So I ran it against a few machines and manually checked the results. I found that while it lists the SCSI controller addresses on the VM they are not properly matching to the VM Hard Disks. All other information is correct. 

     

    Here is the export from the script I got from you:

    Snag_19c47656.png

     

    In the export is shows Hard Disk 2 as using SCSI (1:0) but when I manually checked in VMware Settings is shows that Hard Disk 2 is actually using SCSI (0:1)

    Snag_19d33702.png

     

    I even made sure that the export was showing the same VMDK disk as in settings and it is.

     

    Snag_19d3904d.png

     

     

    If I run the two original scripts I had where I do the Mapping and Lists the SCSI controller addresses separately it does match up to what is in VMware settings.

     

    Snag_19cb2286.png

    Snag_19d33702.png

    Snag_19d3904d.png

    Do you think I'm trying to do too many things at the same time with one script and should keep the two queries separate or do you think there's an easy fix for this? If you think I should separate them into two scripts how can I get the desired effect of having an input file and export file for each separate script?

     

     



  • 9.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 06:39 PM

     so I ran the script against a few VMs and I'm noticing that the SCSI Controller Address isn't matching up.

     

    Snag_19e79b19.png

    For example, If you look at Hard Disk 2 the export says it's using SCSI (1:0) but it's actually using SCSI (0:1)

    Snag_19e89325.png

     

    I even checked the VMDK to make sure that was matching correctly on the Export and it is.

     

    Snag_19e95c61.png

     

    All of the other information on the export is matching up properly. I even ran the original two scripts I mentioned and it too gave me the correct results of 0:1 for Hard Disk 2.

     

    Snag_19ea73cc.png

     

    Is there an easy fix for this or do you think I'm trying to do too much with one script? If I need to run them as two separate scripts how can I have the same desired effect of having an input file with the list of servers and an export with the Server Name and the SCSI addresses?



  • 10.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 06:47 PM

    My bad, I just noticed that I swapped the controller and the disk in the SCSI address.

    It should be

    SCSIAddress = "SCSI($($ctrl.BusNumber):$($vmDisk.ExtensionData.UnitNumber))" 


  • 11.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 07:01 PM

     Yup. That was it. Awesome. Last question and I'll stop bugging you. If I wanted to add the Hard Disk Sizes to a column on the export as well what would I need to change in the script?

    I assume I have to add the values here but I'm not 100% sure what the values that need to be added and how the formatting needs to be changed.

    $curDiskMap = "" | select vmDiskDatastore, vmDiskVmdk, SCSIAddress, vmDiskName, windowsDiskIndex, vmDiskUuid, windowsDeviceID, drives, volumes
                $driveVolumes = $diskToDriveVolume | where {$_.Disk -eq $windowsDisk.DeviceID}
                New-Object -TypeName PSObject -Property ([ordered]@{
                    VM = $vm.Name
                    vmDiskDatastore = $vmDisk.filename.split(']')[0].split('[')[1]
                    vmDiskVmdk = $vmDisk.filename.split(']')[1].trim()
                    SCSIAddress = "SCSI($($ctrl.BusNumber):$($vmDisk.ExtensionData.UnitNumber))" 
                    vmDiskName = $vmDisk.Name
                    windowsDiskIndex = if ($windowsDisk){$windowsDisk.Index}else{"FAILED TO MATCH"}
                    vmDiskUuid = $vmDiskUuid
                    windowsDeviceID = if ($windowsDisk){$windowsDisk.DeviceID}else{"FAILED TO MATCH"}
                    drives = $driveVolumes.DriveLetter
                    volumes = $driveVolumes.VolumeName

     



  • 12.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 07:15 PM

    No problem, add this line

    vmDiskSizeGB = $vmDisk.CapacityGB

     



  • 13.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 08:21 PM

    Great. Everything works perfectly now. I noticed there was another leftover from your original testing when you had the $vmName value.

    if($winHostName){
    $vmDisks = Get-HardDisk -VM $vm | Sort-Object -Property Name
    $vmDatacenterView = Get-VM -Name $vmName | Get-Datacenter | Get-View
    $virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager

    If I'm not mistaken $vmName should be changed to $vm as well. I was getting errors on that until I changed it to $vm. Is that correct?

    if($winHostName){
    $vmDisks = Get-HardDisk -VM $vm | Sort-Object -Property Name
    $vmDatacenterView = Get-VM -Name $vm | Get-Datacenter | Get-View
    $virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager

    Finally, I changed this portion from putting the static credentials inside the powershell script:

    # User with permission to query the WMI on the guest
    $user = 'Username'
    $pswd = 'Password'
    $cred = New-Object -TypeName PSCredential -Argumentlist $user,(ConvertTo-SecureString -String $pswd -AsPlainText -Force)

     

    To this so it just prompts for the credentials so I can share it will my colleagues:

    # User with permission to query the WMI on the guest
    $cred = if ($cred){$cred}else{Get-Credential}

    Thanks again for all your help!

     

     

     



  • 14.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 08:23 PM

    Indeed



  • 15.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 08:27 PM

    Or even better, just

    $vmDatacenterView = Get-Datacenter -VM $vm | Get-View


  • 16.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 08:53 PM

    Here is my final version of the script in case anybody wants to reference it:

     

    # Load PowerCLI Plugin and connect to VCenter Server (Put in your FQDN where it says YOURVCENTERSERVERNAME)
    Import-Module VMware.VimAutomation.Core -ErrorAction SilentlyContinue
    connect-viserver YOURVCENTERSERVERNAME
    
    # User with permission to query the WMI on the guest
    $cred = if ($cred){$cred}else{Get-Credential}
    
    # CSV file with a column named vmName
    Import-Csv -Path .\vmnames.csv -UseCulture -PipelineVariable row |
    ForEach-Object -Process {
        $vm = Get-VM -Name $row.vmName
    
        # If the script can't determine the FQDN of the Guest OS, the VM is skipped
        $winHostName = ''
        if($vm.Guest.State -eq 'Running'){
            if($vm.Guest.HostName -ne ''){
                $WinHostName = $vm.Guest.HostName
            }
            elseif($vm.Guest.IPAddress){
                $resolve = Resolve-DnsName -Name $vm.guest.IPAddress[0]
                if($resolve){
                    $WinHostName = $resolve.NameHost
                }
            }
        }
        if($winHostName){
            $vmDisks = Get-HardDisk -VM $vm | Sort-Object -Property Name
            $vmDatacenterView = Get-Datacenter -VM $vm | Get-View
            $virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager
            
            # Getting the list of Windows disks and partitions using WMI
            $winDisk = Get-WmiObject -Class Win32_DiskDrive -ComputerName $WinHostName -Credential $cred
            $diskToDriveVolume = Get-WmiObject Win32_DiskDrive -ComputerName $WinHostName -Credential $cred| % {
                $disk = $_
                $partitions = "ASSOCIATORS OF " +
                    "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +
                    "WHERE AssocClass = Win32_DiskDriveToDiskPartition"
                Get-WmiObject -Query $partitions -ComputerName $WinHostName -Credential $cred| % {
                    $partition = $_
                    $drives = "ASSOCIATORS OF " +
                        "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +
                        "WHERE AssocClass = Win32_LogicalDiskToPartition"
                    Get-WmiObject -Query $drives -ComputerName $WinHostName -Credential $cred| % {
                        New-Object -Type PSCustomObject -Property @{
                            Disk = $disk.DeviceID
                            DriveLetter = $_.DeviceID
                            VolumeName = $_.VolumeName
                        }
                    }
                }
            }
            #Getting a disk serial number
            foreach ($disk in $winDisk)
            {
                $disk | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null
                $diskSerialNumber = $disk.SerialNumber
                if ($disk.Model -notmatch 'VMware Virtual disk SCSI Disk Device')
                {
                    if ($diskSerialNumber -match '^\S{12}$'){$diskSerialNumber = ($diskSerialNumber | foreach {[byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} } ) -join ''}
                    $disk.AltSerialNumber = $diskSerialNumber
                }
            }
            #Searching all VM disks and matching them with Windows disks by their SerialNumber / UUID
            foreach ($vmDisk in $vmDisks)
            {
                $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')}
                $windowsDisk = $winDisk | where {$_.SerialNumber -eq $vmDiskUuid}
                if (-not $windowsDisk){
                    $windowsDisk = $winDisk | where {$_.AltSerialNumber -eq $vmDisk.ScsiCanonicalName.substring(12,24)}
                }
                $ctrl = $vm.ExtensionData.Config.Hardware.Device | where{$_.Key -eq $vmDisk.ExtensionData.ControllerKey}
                $curDiskMap = "" | select vmDiskDatastore, vmDiskVmdk, SCSIAddress, vmDiskName, windowsDiskIndex, vmDiskUuid, windowsDeviceID, drives, volumes
                $driveVolumes = $diskToDriveVolume | where {$_.Disk -eq $windowsDisk.DeviceID}
                New-Object -TypeName PSObject -Property ([ordered]@{
                    VM = $vm.Name
                    vmDiskDatastore = $vmDisk.filename.split(']')[0].split('[')[1]
                    vmDiskVmdk = $vmDisk.filename.split(']')[1].trim()
                    SCSIAddress = "SCSI($($ctrl.BusNumber):$($vmDisk.ExtensionData.UnitNumber))" 
                    vmDiskName = $vmDisk.Name
                    vmDiskSizeGB = $vmDisk.CapacityGB
                    windowsDiskIndex = if ($windowsDisk){$windowsDisk.Index}else{"FAILED TO MATCH"}
                    vmDiskUuid = $vmDiskUuid
                    windowsDeviceID = if ($windowsDisk){$windowsDisk.DeviceID}else{"FAILED TO MATCH"}
                    drives = $driveVolumes.DriveLetter
                    volumes = $driveVolumes.VolumeName
                    
                })
            }
        }
        else{
            Write-Host "Could not determine FQDN for VM ($vm.Name)"
        }
    } | Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture

     

     

    Make sure when you're running the PowerShell script that you are in the working directory first where the vmnames.csv file resides. Otherwise it'll complain it can't find the vmnames.csv file. All of the VMs you want to run this against need to go in this file. This will also be the same directory that the report.csv exports to. 

     

    You can do a search and export the list of VMs from the Virtual Machines view in vCenter so you don't have to type them all out by hand if you have a lot.

     

    Another issue I had was some VMs were affected by a vSphere 6.5 bug where the "disk.EnableUUID = "TRUE" value was missing from multiple vmx configuration files. I'll have to go back and fix that on those VMs.  Without that value the Uuid is not exposed to the Guest OS. Therefore, it can't match the drives up. 

     

    You can reference that KB article here.

    https://kb.vmware.com/s/article/52815

     

    Finally, As  mentioned. This is not a fool proof method and only works under the right conditions. Your mileage may vary. 

    HUGE THANKS to . I wouldn't have even known where to begin (or end) without his help!

     



  • 17.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 08:59 PM

    Here is my final version of the script in case anybody wants to reference it:

    # Load PowerCLI Plugin and connect to VCenter Server (Put in your FQDN where it says YOURVCENTERSERVERNAME)
    Import-Module VMware.VimAutomation.Core -ErrorAction SilentlyContinue
    connect-viserver YOURVCENTERSERVERNAME
    
    # User with permission to query the WMI on the guest
    $cred = if ($cred){$cred}else{Get-Credential}
    
    # CSV file with a column named vmName
    Import-Csv -Path .\vmnames.csv -UseCulture -PipelineVariable row |
    ForEach-Object -Process {
        $vm = Get-VM -Name $row.vmName
    
        # If the script can't determine the FQDN of the Guest OS, the VM is skipped
        $winHostName = ''
        if($vm.Guest.State -eq 'Running'){
            if($vm.Guest.HostName -ne ''){
                $WinHostName = $vm.Guest.HostName
            }
            elseif($vm.Guest.IPAddress){
                $resolve = Resolve-DnsName -Name $vm.guest.IPAddress[0]
                if($resolve){
                    $WinHostName = $resolve.NameHost
                }
            }
        }
        if($winHostName){
            $vmDisks = Get-HardDisk -VM $vm | Sort-Object -Property Name
            $vmDatacenterView = Get-Datacenter -VM $vm | Get-View
            $virtualDiskManager = Get-View -Id VirtualDiskManager-virtualDiskManager
            
            # Getting the list of Windows disks and partitions using WMI
            $winDisk = Get-WmiObject -Class Win32_DiskDrive -ComputerName $WinHostName -Credential $cred
            $diskToDriveVolume = Get-WmiObject Win32_DiskDrive -ComputerName $WinHostName -Credential $cred| % {
                $disk = $_
                $partitions = "ASSOCIATORS OF " +
                    "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +
                    "WHERE AssocClass = Win32_DiskDriveToDiskPartition"
                Get-WmiObject -Query $partitions -ComputerName $WinHostName -Credential $cred| % {
                    $partition = $_
                    $drives = "ASSOCIATORS OF " +
                        "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +
                        "WHERE AssocClass = Win32_LogicalDiskToPartition"
                    Get-WmiObject -Query $drives -ComputerName $WinHostName -Credential $cred| % {
                        New-Object -Type PSCustomObject -Property @{
                            Disk = $disk.DeviceID
                            DriveLetter = $_.DeviceID
                            VolumeName = $_.VolumeName
                        }
                    }
                }
            }
            #Getting a disk serial number
            foreach ($disk in $winDisk)
            {
                $disk | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null
                $diskSerialNumber = $disk.SerialNumber
                if ($disk.Model -notmatch 'VMware Virtual disk SCSI Disk Device')
                {
                    if ($diskSerialNumber -match '^\S{12}$'){$diskSerialNumber = ($diskSerialNumber | foreach {[byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} } ) -join ''}
                    $disk.AltSerialNumber = $diskSerialNumber
                }
            }
            #Searching all VM disks and matching them with Windows disks by their SerialNumber / UUID
            foreach ($vmDisk in $vmDisks)
            {
                $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')}
                $windowsDisk = $winDisk | where {$_.SerialNumber -eq $vmDiskUuid}
                if (-not $windowsDisk){
                    $windowsDisk = $winDisk | where {$_.AltSerialNumber -eq $vmDisk.ScsiCanonicalName.substring(12,24)}
                }
                $ctrl = $vm.ExtensionData.Config.Hardware.Device | where{$_.Key -eq $vmDisk.ExtensionData.ControllerKey}
                $curDiskMap = "" | select vmDiskDatastore, vmDiskVmdk, SCSIAddress, vmDiskName, windowsDiskIndex, vmDiskUuid, windowsDeviceID, drives, volumes
                $driveVolumes = $diskToDriveVolume | where {$_.Disk -eq $windowsDisk.DeviceID}
                New-Object -TypeName PSObject -Property ([ordered]@{
                    VM = $vm.Name
                    vmDiskDatastore = $vmDisk.filename.split(']')[0].split('[')[1]
                    vmDiskVmdk = $vmDisk.filename.split(']')[1].trim()
                    SCSIAddress = "SCSI($($ctrl.BusNumber):$($vmDisk.ExtensionData.UnitNumber))" 
                    vmDiskName = $vmDisk.Name
                    vmDiskSizeGB = $vmDisk.CapacityGB
                    windowsDiskIndex = if ($windowsDisk){$windowsDisk.Index}else{"FAILED TO MATCH"}
                    vmDiskUuid = $vmDiskUuid
                    windowsDeviceID = if ($windowsDisk){$windowsDisk.DeviceID}else{"FAILED TO MATCH"}
                    drives = $driveVolumes.DriveLetter
                    volumes = $driveVolumes.VolumeName
                    
                })
            }
        }
        else{
            Write-Host "Could not determine FQDN for VM ($vm.Name)"
        }
    } | Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture

     

    Make sure when you're running the PowerShell script that you are in the working directory first where the vmnames.csv file resides. Otherwise it'll complain it can't find the vmnames.csv file. All of the VMs you want to run this against need to go in this file. This will also be the same directory that the report.csv exports to. 

     

    You can do a search and export the list of VMs from the Virtual Machines view in vCenter so you don't have to type them all out by hand if you have a lot.

     

    Another issue I had was some VMs were affected by a vSphere 6.5 bug where the "disk.EnableUUID = "TRUE" value was missing from multiple vmx configuration files. I'll have to go back and fix that on those VMs.  Without that value the Uuid is not exposed to the Guest OS. Therefore, it can't match the drives up. 

     

    You can reference that KB article here.

    https://kb.vmware.com/s/article/52815

     

    Finally, As @LucD mentioned. This is not a fool proof method and only works under the right conditions. Your mileage may vary. 

    HUGE THANKS to @LucD. I wouldn't have even known where to begin (or end) without his help!



  • 18.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 21, 2023 01:42 PM

    Hi

    When I try to run the script, getting below errors:

     

    You cannot call a method on a null-valued expression.
    At C:\Users\XODXCAKUppu\Desktop\vdisk.ps1:69 char:50
    + ... sk | where {$_.SerialNumber -eq $vmDisk.ScsiCanonicalName.substring(1 ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

     

    Kindly assist to fix. thanks,

    Reach me @ k_anandhan@hotmail.com or skanandhan@gmail.com 



  • 19.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 21, 2023 02:15 PM

    Which script and which line?
    I can't find the line mentioned in the error message



  • 20.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 21, 2023 02:22 PM

    Mapping VMWare vmdk disk to OS Disk mapping script.

    The last line : $_.AltSerialNumber - giving error

     

    #Getting a disk serial number
    foreach ($disk in $winDisk)
    {
    $disk | Add-Member -MemberType NoteProperty -Name AltSerialNumber -Value $null
    $diskSerialNumber = $disk.SerialNumber
    if ($disk.Model -notmatch 'VMware Virtual disk SCSI Disk Device')
    {

    if ($diskSerialNumber -match '^\S{12}$'){$diskSerialNumber = ($diskSerialNumber | foreach {[byte[]]$bytes = $_.ToCharArray(); $bytes | foreach {$_.ToString('x2')} } ) -join ''}
    $disk.AltSerialNumber = $diskSerialNumber
    }
    }
    #Searching all VM disks and matching them with Windows disks by their SerialNumber / UUID
    $diskMaps = @()

    foreach ($vmDisk in $vmDisks)
    {
    $vmDiskUuid = $virtualDiskManager.queryvirtualdiskuuid($vmDisk.Filename, $vmDatacenterView.MoRef) | foreach {$_.replace(' ','').replace('-','')}
    $windowsDisk = $winDisk | where {$_.SerialNumber -eq $vmDiskUuid}

     if (-not $windowsDisk){$windowsDisk = $winDisk | where {$_.AltSerialNumber -eq $vmDisk.ScsiCanonicalName.substring(12,24)}}

     

     

    ======== Output ===

    You cannot call a method on a null-valued expression.
    At C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1:926 char:59
    + ... sk | where {$_.SerialNumber -eq $vmDisk.ScsiCanonicalName.substring(1 ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1:926 char:59
    + ... sk | where {$_.SerialNumber -eq $vmDisk.ScsiCanonicalName.substring(1 ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

     

    vmDiskDatastore vmDiskVmdk vmDiskName vmDiskUuid windowsDeviceID drives volumes size freespace windowsDiskIndex
    --------------- ---------- ---------- ---------- --------------- ------ ------- ---- --------- ----------------
    DS7_CLO01_04 DZAP91/DZAP91_4.vmdk Hard disk 1 6000C29d3c24c0481d7fc608b0ae55e5 FAILED TO MATCH 0.00GB 0.00GB FAILED TO MATCH
    DS7_CLO01_04 DZAP91/DZAP91_1.vmdk Hard disk 2 6000C29264e150ce413ade616404070b FAILED TO MATCH 0.00GB 0.00GB FAILED TO MATCH



  • 21.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 21, 2023 02:28 PM

    The script is not working Windows Server 2016 & above OS version, getting the same error. But it is working for Windows Server 2012 r2 and below.



  • 22.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 21, 2023 02:58 PM

    The error message says "$_.SerialNumber", not "$_.AltSerialNumber".
    Did you check your code?



  • 23.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 21, 2023 03:30 PM
      |   view attached

    Hi,

    I have modified the script as function, the majority of your part is unchanged.

    But still getting the same error.

    Please find attached the script file.

    Kindly review and advise. thanks. Awaiting your reply.

    Attachment(s)



  • 24.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 21, 2023 05:30 PM

    The code you attached does not contain the line mentioned in the error message.



  • 25.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 22, 2023 03:49 AM

    Hi LucD,

    Please find the attached screenshot. When I execute the script for Win2012r2, it works, but above Win2012 I get the error, which points to $_.Altserialnumber line:70,char:59.

    Is it possible can us to connect via Zoom/teams? If yes send an email (skanandhan@gmail.com or anandhank@dxc.com), please much appreciated.

    script error.png



  • 26.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 22, 2023 08:53 AM

    Sorry, I don't do that.
    It would become a full-day occupation if I start doing that.



  • 27.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 22, 2023 09:00 AM

    Np,

    Could you please help me on the script? Did you check the attached snapshots? any suggestion?



  • 28.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 22, 2023 09:25 AM

    As far as I can tell, the error is caused by the Substring method, not the AltSerial property.
    You would have to check what is actually in $vmDisk at that point.



  • 29.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 22, 2023 09:32 AM

    Do you have an alternative script to pull the disk map report for Windows 2019?



  • 30.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 22, 2023 09:38 AM

    No, I don't.
    In fact, there is no foolproof method for mapping vDisks to Windows partitions.
    It only works in certain situations.

    Isn't the Get-VMGuestDisk cmdlet returning part of that information?
    Note that there are some prereqs for that cmdlet to work.



  • 31.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Sep 25, 2023 06:33 PM

    Hi LucD,

    Find the issue. Windows Server 2019 server OS unable to register the disk serial number.

    In another vmware form, found the solution to update the VM property disk.EnableUUID set to True value. Then shutdown and boot the virtual machine. Now it is working.

    Thanks for your help.



  • 32.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 24, 2020 09:06 PM

    Here is my final version of the script in case anybody wants to reference it:

     

     

     

     

    Make sure when you're running the PowerShell script that you are in the working directory first where the vmnames.csv file resides. Otherwise it'll complain it can't find the vmnames.csv file. All of the VMs you want to run this against need to go in this file. This will also be the same directory that the report.csv exports to. 

     

    You can do a search and export the list of VMs from the Virtual Machines view in vCenter so you don't have to type them all out by hand if you have a lot.

     

    Another issue I had was some VMs were affected by a vSphere 6.5 bug where the "disk.EnableUUID = "TRUE" value was missing from multiple vmx configuration files. I'll have to go back and fix that on those VMs.  Without that value the Uuid is not exposed to the Guest OS. Therefore, it can't match the drives up. 

     

    You can reference that KB article here.

    https://kb.vmware.com/s/article/52815

     

    Finally, As @LucD mentioned. This is not a fool proof method and only works under the right conditions. Your mileage may vary. 

    HUGE THANKS to @LucD. I wouldn't have even known where to begin (or end) without his help!



  • 33.  RE: Script to Map Windows and VMware Disks as well as VMware SCSI Controller configuration

    Posted Nov 25, 2020 02:47 AM

    Here is my final version of the script in case anybody wants to reference it:

    Make sure when you're running the PowerShell script that you are in the working directory first where the vmnames.csv file resides. Otherwise it'll complain it can't find the vmnames.csv file. All of the VMs you want to run this against need to go in this file. This will also be the same directory that the report.csv exports to.

     

    You can do a search and export the list of VMs from the Virtual Machines view in vCenter so you don't have to type them all out by hand if you have a lot.

     

    Another issue I had was some VMs were affected by a vSphere 6.5 bug where the "disk.EnableUUID = "TRUE" value was missing from multiple vmx configuration files. I'll have to go back and fix that on those VMs. Without that value the Uuid is not exposed to the Guest OS. Therefore, it can't match the drives up.

     

    You can reference that KB article here.

    https://kb.vmware.com/s/article/52815

     

    Finally, As mentioned. This is not a fool proof method and only works under the right conditions. Your mileage may vary.

    HUGE THANKS to . I wouldn't have even known where to begin (or end) without his help!