VMware Cloud Community
AlbertWT
Virtuoso
Virtuoso
Jump to solution

PowerCLI script to lists Windows Drive letter and VM Disk number in Data center ?

Hi All,

Can anyone here please assist me with the powershell script if possible to list the VM information like the following format or in CSV format is OK:

SCSI (0:0) VM Hard Disk 1 [R5D23] PRODFSCLUS01-VM/PRODFSCLUS01-VM.vmdk - Windows C: drive - 60 GB

SCSI (1:1) VM Hard Disk 2 [NAS-D76] PRODFSCLUS01-VM/PRODFSCLUS01-VM.vmdk - Windows Q: drive - 1 GB

SCSI (1:2) VM Hard Disk 3 [NAS-D23] PRODFSCLUS01-VM/PRODFSCLUS01-VM.vmdk - Windows G: drive - 1.77 TB

SCSI (1:3) VM Hard Disk 4 [R5D52] PRODFSCLUS01-VM/PRODFSCLUS01-VM.vmdk - Windows H: drive - 1.77 GB

SCSI (1:4) VM Hard Disk 5 [NAS-D19] PRODFSCLUS01-VM/PRODFSCLUS01-VM.vmdk - Windows T: drive - 60 GB

Thanks in advance.

/* Please feel free to provide any comments or input you may have. */
50 Replies
LucD
Leadership
Leadership
Jump to solution

What you are seeing is the default output from that WMI object.
If you want to see different properties, you will have to use the Select-Object cmdlet


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

Reply
0 Kudos
bikashyadav
Contributor
Contributor
Jump to solution

Hi LucD,

Since you saw the output result n it's clear that only invoke-vmscript gives me a valid output.if I run Get-Ciminstance for a remote computer it doesn't work n I have to use invoke-vmscript to get Get-Ciminstance output.

So how do I modify this script as and use invoke-vmscript.

$compName = 'MyVM'

$volTab = @{}

foreach($disk in (Get-CimInstance -ComputerName $compName -ClassName Win32_DiskDrive)){

    foreach($partition in (Get-CimAssociatedInstance -InputObject $disk -ResultClassName Win32_DiskPartition)){

        Get-CimAssociatedInstance -InputObject $partition -ResultClassName Win32_LogicalDisk | %{

            $volTab.Add("$($disk.SCSIBus):$($disk.SCSITargetId)",($_.DeviceID,$_.VolumeName -join '|'))

        }

    }

}

$vm = Get-VM -Name $compName

foreach($ctrl in Get-ScsiController -VM $vm){

    foreach($disk in (Get-HardDisk -VM $vm | where{$_.ExtensionData.ControllerKey -eq $ctrl.Key})){

        $obj = [ordered]@{

            VM = $vm.name

            HD = $disk.Name

            VMDK = $disk.Filename

            Device = "$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"

            Drive = ""

            Label = ""

        }

        if($volTab.ContainsKey("$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)")){

            $obj.Drive = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[0]

            $obj.Label = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[1]

        }

        New-Object -TypeName PSObject -Property $obj

    }

}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Instead of transferring the complete WMI object, you can do the extraction of the required properties on the target station.

Use this as an example.
It transfers the required data in CSV format, which on the calling side is then converted back to an object.

Which you can use in your script

$vmName = 'MyVM'

$user = 'domain\user'

$pswd = 'VMware1!'


$secPswd = ConvertTo-SecureString -String $pswd -AsPlainText -Force

$cred = New-Object System.Management.Automation.PSCredential ($user, $secPswd)


$code = @'

$info = foreach($disk in (Get-CimInstance -ClassName Win32_DiskDrive)){

    foreach($partition in (Get-CimAssociatedInstance -InputObject $disk -ResultClassName Win32_DiskPartition)){

        Get-CimAssociatedInstance -InputObject $partition -ResultClassName Win32_LogicalDisk | select DeviceID, VolumeName,

            @{ label = "SCSITarget"; expression = {$disk.SCSITargetId} },

            @{ label = "SCSIBus"; expression = {$disk.SCSIPort-2} }

    }

}

$info | ConvertTo-Csv -NoTypeInformation -UseCulture

'@


$vm = Get-VM -Name $vmName


$sInvoke = @{

    VM = $VM

    ScriptType = 'Powershell'

    ScriptText = $code

    GuestCredential = $cred

}

Invoke-VMScript @sInvoke |

Select -ExpandProperty ScriptOutput |

ConvertFrom-Csv -UseCulture


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

Reply
0 Kudos
JPD1109
Contributor
Contributor
Jump to solution

I too wanted to determine the association between vmware scsi devices and their windows partitions and drive letters. 

Starting with the information gleaned from  Map VMware virtual disks and Windows drive volumes with a PowerShell script – 4sysops​ I knew I could not reliably match Windows and VMWare SCSI bus numbers.  I was on my own.  I started by generating detailed information from both VMWare and Windows environments.  I then summarized each environment's SCSI controller information based on number of SCSI target IDs and total disk space used on all drives.  I discovered that once I sorted these summaries, I could see a one-to-one mapping between the VMWare and Windows SCSI controllers.  Once I had a valid mapping, I could then update my VMWare report with the missing Windows information (serial number, disk size, number of partitions, drive letters). 

If WMI is accessible for the VMs in question, the script will map VMWare to Windows partitions.  If WMI is not available, it will at least show you the VMWare side of the equation.

LucD
Leadership
Leadership
Jump to solution

You might want to have a look at the Get-VMGuestDisk cmdlet, new in PowerCLI 12.0.


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

JPD1109
Contributor
Contributor
Jump to solution

Get-VMGuestDisk requires vSphere version 7.0 and later.

Reply
0 Kudos
bikashyadav
Contributor
Contributor
Jump to solution

Seems like Get-VMGuestDisk requires vsphere 7 and later plus vmtool 11.x

LucD
Leadership
Leadership
Jump to solution

That is correct, those are some of the requirements.


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

velum1000
Contributor
Contributor
Jump to solution

Hi LucD,

Still stuggling to get the Drive letter and disk number on single report.

was tried for class-  Win32_DiskDrive command to get the report got failed "WinRM error"

there is any possibility t get the report using vm.Guest.Disks command along with harddisk number

$DiskInfo= @()

foreach ($VMview in Get-VM VMname | Get-View){

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 VMname, SCSIController, DiskName, SCSI_ID, DeviceName, DiskFile, DiskSize

$VirtualDisk.VMname = $VMview.Name

$VirtualDisk.SCSIController = $VirtualSCSIController.DeviceInfo.Label

$VirtualDisk.DiskName = $VirtualDiskDevice.DeviceInfo.Label

$VirtualDisk.SCSI_ID = "$($VirtualSCSIController.BusNumber) : $($VirtualDiskDevice.UnitNumber)"

$VirtualDisk.DeviceName = $VirtualDiskDevice.Backing.DeviceName

$VirtualDisk.DiskFile = $VirtualDiskDevice.Backing.FileName

$VirtualDisk.DiskSize = $VirtualDiskDevice.CapacityInKB * 1KB / 1GB

$DiskInfo +=$VirtualDisk

}}}

$DiskInfo | sort VMname, Diskname | Export-Csv -Path C:\temp\server.csv

ForEach-Object {$vm.Guest.Disks | ForEach-Object {

    $VirtualDisk1 = "" | Select-Object -Property Path,capacity

    $VirtualDisk1.Path = $_.Path

    $VirtualDisk1.Capacity = $_.Capacity

$DiskInfo +=$VirtualDisk1

  }

}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not sure if you have read my previous comments, but there is no fool-proof method to map Guest OS partitions/drives to VMDK files.

With Get-VMGuestDisk this has changed, but there are prerequisites.


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

velum1000
Contributor
Contributor
Jump to solution

Thank you for the information ,

finally as per your suggesting have made below script , please help to add to scsicanonicalname and export to csv format.

$volTab = @{}

foreach($disk in (Get-CimInstance  -ClassName Win32_DiskDrive)){

    foreach($partition in (Get-CimAssociatedInstance -InputObject $disk -ResultClassName Win32_DiskPartition)){

        Get-CimAssociatedInstance -InputObject $partition -ResultClassName Win32_LogicalDisk | %{

            $volTab.Add("$($disk.SCSIBus):$($disk.SCSITargetId)",($_.DeviceID,$_.VolumeName -join '|'))

        }

    }

}

foreach($ctrl in Get-ScsiController -VM $vm){

    foreach($disk in (Get-HardDisk -VM $vm | where{$_.ExtensionData.ControllerKey -eq $ctrl.Key})){

        $obj = [ordered]@{

            VM = $vm.name

            HD = $disk.Name

            VMDK = $disk.Filename

            Device = "$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"

            Drive = ""

            Label = ""

        }

        if($volTab.ContainsKey("$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)")){

            $obj.Drive = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[0]

            $obj.Label = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[1]

        }

        New-Object -TypeName PSObject -Property $obj

    }

}

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso
Jump to solution

So not even Vmware Tools v11 and ESXi v7 can get consistent result from PowerCLI?

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

There are also some prerequisites on the Guest OS, although it seems to work on several Linux based Guest OS.

Another limiting factor is apparently the filesystem type used, I haven't found a definitive list of which types are supported or not.

Are you seeing issues?
On which Guest OS and which filesystem type?


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

Reply
0 Kudos
bikashyadav
Contributor
Contributor
Jump to solution

Hi LucD,

Below scripts work for me. Can you help me modify the below script to get linux machine details.

param ([ string ]$VMName )

#Define computername

$computer = $VMName

$VMView = Get-VM -Name $computer | Get-View

$ServerDiskToVolume = @(

Get-WmiObject -Class Win32_DiskDrive | foreach {

$Dsk = $_

$query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='$($_.DeviceID)'} WHERE ResultClass=Win32_DiskPartition"

Get-WmiObject -Query $query | foreach {

$query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='$($_.DeviceID)'} WHERE ResultClass=Win32_LogicalDisk"

Get-WmiObject -Query $query | Select DeviceID,

VolumeName,

@{ label = "SCSITarget"; expression = {$dsk.SCSITargetId} },

@{ label = "SCSIBus"; expression = {$dsk.SCSIBus} }

}

}

)

$VMDisks = 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}))

{

$MatchingDisk = @( $ServerDiskToVolume | Where {$_.SCSITarget -eq $VirtualDiskDevice.UnitNumber -and $_.SCSIBus -eq $VirtualSCSIController.BusNumber} )

[pscustomobject]@{

VM = $VMView.Name

#HostName = $VMView.Guest.HostName

DiskFile = $VirtualDiskDevice.Backing.FileName

DiskName = $VirtualDiskDevice.DeviceInfo.Label

DiskSizeGB = $VirtualDiskDevice.CapacityInKB / 1024KB

#SCSIController = $VirtualSCSIController.BusNumber

#SCSITarget = $VirtualDiskDevice.UnitNumber

SCSIid = "$($VirtualSCSIController.BusNumber):$($VirtualDiskDevice.UnitNumber)"

DeviceID = $MatchingDisk.DeviceID

}

}

}

$VMDisks | ft -AutoSize

Thanks

Bikash

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I don't know how many times I have to repeat this but there is no foolproof method, before Get-VMGuestDisk, of mapping Guest OS partitions/drives to VMDK.

Your script "works" for a Windows Guest OS and in your specific situation.

The script is partially based on some Windows methods and properties that do not exist in a Linux Guest OS.

There is no straight-forward way to replicate that script for a Linux Guest OS.


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

Reply
0 Kudos
velum1000
Contributor
Contributor
Jump to solution

Hi Lucd,

pls assist export the result to csv file, this script is working , only required only export outupt file and due to remote execution policy "Win32_DiskDrive.DeviceID " is not working on our premises,

$volTab = @{}

foreach($disk in (Get-CimInstance  -ClassName Win32_DiskDrive)){

    foreach($partition in (Get-CimAssociatedInstance -InputObject $disk -ResultClassName Win32_DiskPartition)){

        Get-CimAssociatedInstance -InputObject $partition -ResultClassName Win32_LogicalDisk | %{

            $volTab.Add("$($disk.SCSIBus):$($disk.SCSITargetId)",($_.DeviceID,$_.VolumeName -join '|'))

        }

    }

}

foreach($ctrl in Get-ScsiController -VM $vm){

    foreach($disk in (Get-HardDisk -VM $vm | where{$_.ExtensionData.ControllerKey -eq $ctrl.Key})){

        $obj = [ordered]@{

            VM = $vm.name

            HD = $disk.Name

            VMDK = $disk.Filename

            Device = "$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"

            Drive = ""

            Label = ""

        }

        if($volTab.ContainsKey("$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)")){

            $obj.Drive = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[0]

            $obj.Label = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[1]

        }

        New-Object -TypeName PSObject -Property $obj

    }

}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The foreach statement doesn't place anything in the pipeline.

It is easier to use the Foreach-Object cmdlet in combination with the Pipeline parameter.

Like this

Get-ScsiController -VM $vm -PipelineVariable ctrl |

ForEach-Object -Process {

    Get-HardDisk -VM $vm -PipelineVariable disk | where{$_.ExtensionData.ControllerKey -eq $ctrl.Key} |

    ForEach-Object -Process {

        $obj = [ordered]@{

            VM = $vm.name

            HD = $disk.Name

            VMDK = $disk.Filename

            Device = "$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"

            Drive = ""

            Label = ""

        }

        if($volTab.ContainsKey("$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)")){

            $obj.Drive = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[0]

            $obj.Label = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[1]

        }

        New-Object -TypeName PSObject -Property $obj

    }

} | Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture


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

Reply
0 Kudos
winsolo
Enthusiast
Enthusiast
Jump to solution

Thanks for the script. It worked.

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

Reply
0 Kudos
DavidGriswoldeB
Enthusiast
Enthusiast
Jump to solution

I know this is an old thread, but I took some snippets from the code included and built something that works with VMware 6.7. The next step is including the process to expand the VMDK and then expand in the OS. I will post that script in a new thread once it is working. Note: I wanted Size, not Lable, but that is an easy change.

$vmName = 'MyVM'
$user = 'domain\user'
$pswd = 'password'

$secPswd = ConvertTo-SecureString -String $pswd -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($user, $secPswd)


$code = @'
$compName = '.'
$test = $null
foreach($disk in (Get-CimInstance -ComputerName $compName -ClassName Win32_DiskDrive)){
foreach($partition in (Get-CimAssociatedInstance -InputObject $disk -ResultClassName Win32_DiskPartition)){
Get-CimAssociatedInstance -InputObject $partition -ResultClassName Win32_LogicalDisk | %{
$test += "$($disk.SCSIBus):$($disk.SCSITargetId)","=",($_.DeviceID),"|",[math]::round($_.size/1024/1024/1024) -join ""
$test += "`r`n"
}
}
}
$test
'@


$vm = Get-VM -Name $vmName

$sInvoke = @{
VM = $VM
ScriptType = 'Powershell'
ScriptText = $code
GuestCredential = $cred
}

$volTab = @{}
$volTab = Invoke-VMScript @sInvoke | Select -ExpandProperty ScriptOutput | ConvertFrom-StringData

$vm = Get-VM -Name $vmName

foreach($ctrl in Get-ScsiController -VM $vm){
foreach($disk in (Get-HardDisk -VM $vm | where{$_.ExtensionData.ControllerKey -eq $ctrl.Key})){
$obj = [ordered]@{
VM = $vm.name
HD = $disk.Name
VMDK = $disk.Filename
Device = "$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"
Drive = ""
Size = ""
}

if($volTab.ContainsKey("$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)")){
$obj.Drive = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[0]
$obj.Size = $volTab["$($ctrl.ExtensionData.BusNumber):$($disk.ExtensionData.UnitNumber)"].Split('|')[1]
}
New-Object -TypeName PSObject -Property $obj
}
}

 

Reply
0 Kudos