Where’s that vmdk at?

Do your vm’s have multiple virtual disks? Do you use different datastores for your vmdk’s? Are you ever wondering where the disk files of each of your vm’s is stored? Yes? Well, I’ve got something to help you out.

Today’s handy script of the day creates an overview of the locations of all your vmdk files in the form of a csv file.

Of course you Powershell guru’s can work some simple magic to output it to a HTML page, a Word document of straight to the printer. (If you don’t, but would like to, drop me a comment and I’ll try to respond asap).

The script is attached for easy use. Just fill in your Virtual Center server name, rename the file to .ps1 and enjoy!



Powershell Oneliner #5

Why I love Powershell:

Yesterday I needed to create an overview of people, their department name and office location. I wanted to have this list in Excel. But all I had was a textfile with their names. A tedious task to fill in all this information, one might think. Luckily, I know Powershell:

Get-Content "D:scriptspeople.txt" | % { Get-QADUser -Name $_ } | Select-Object Name, Department, Office | Export-Csv -Path "D:scriptsoverview.csv" -NoTypeInformation

This simple oneliner generated the entire overview for me in the blink of an eye! My colleagues were flabbergasted 🙂

Gotta love it.

My Scripting Contest Contribution

It’s done!

Today I have finished my script for the VI Toolkit Scripting Contest. This contest celebrates the release of the VI Toolkit for Windows; a collection of cmdlets for Windows Powershell that allow you to manage your VMware Infrastructure.

Alle the entries for the contest are available for public use. In fact, one of the requirements for the scripts is that they can be used by (and are useful for) anyone. Although you are very welcome to join the VI Toolkit Community and share your knowlegde, I understand some of you would rather just download the code and get it running, without the hassle of registering. So, I have decided to publish my contest entry here on my website for all of you to use and/or study. You can even use (parts of) it for your own contribution to the contest. I don’t mind. It helps us all in the long run.

Here’s the explanation of the script, as I posted it in the contest community:

Many VMware environments will consist of multiple ESX servers, with multiple HBAs, connecting to multiple SCSI Targets, having access to multiple LUNs, which are used as extents for numerous datastores. In order to be able to use Vmotion, all LUNs should be accessible on all ESX hosts in a cluster. And in order to ensure reliability and availability, each component in the chain will have to be redundant. This amounts to multiple paths to each LUN, from each ESX host. While your environment grows, the number of paths grows exponentially. My script allows you to analyse complex environments and check for missing links, misconfigurations such as a LUN not masked to one of your ESX hosts or a multipath policy that is set to a wrong value.

My Get-StorageInfo script processes all LUNs connected to ESX Servers within a specified VMware Cluster. It builds a custom collection of objects representing these LUNs, with the following properties: VMHost, LUNPath, Policy, Prefer, Datastore, Vendor, Model, VMHBA, SCSITarget, LUNID, LUNKey. The script should be dot-sourced to allow the user to view, filter and sort this collection. The script will check if it is being dot-sourced. The script also prvides the user with two functions for common sorting and filtering tasks, as well as two examples for using them.

Type Show-DatastorePaths for an overview of LUNs and path counts.

Type Show-LUNs for a detailed overview of Luns, which can be filtered by using the following parameters: VMHost, LUNID, Policy, Datastore, Vendor, Model.


Show-LUNs -Datastore PRD -Policy mru #Finds LUNs where the datastore name contains PRD and the policy is set to MRU

$LUNCollection | Where{$_.Datastore -eq $null} | Group-Object LUNID #Shows LUN IDs that have no datastore name (e.g. RDMs or unused LUNs)

A bit more info on the inner workings of the script:

In order to get all LUNs via all different paths I go through a set of nested loops. First looping through all VMHosts in the cluster, then looping through VMHBAs, then SCSI Targets and finally LUNs.

Not all properties I wanted to use are available within these loops. Therefore, for each VMHost a collection is built containing the relationship between Datastore names and Extents (in the form of a LUN path e.g. vmhba1:0:123). This allows the script to link the datastore name to those LUN paths that are actively used. The multipath policy and preferred path and the Vendor and Model of the LUN storage device are also found by using the LUN path.

After looping through all of the above, only a fraction of the LUN references have all the properties filled in: the actively used ones. Next, the script loops through the entire collection of LUN references in the collection, matching references to the same LUN by comparing the LUNKey or UUID and copying the properties that were empty.

That’s a lot of looping, I hear you think. That’s right. And it will take some time to complete. In our environment it takes about ten minutes generating the entire collection of 1440 references to different LUNs. But the result is a very rich array of items which – using the awesome power of Powershell – can generate a lot of usefull information for your environment.



  • Easy to use input prompt and menu eliminate the need to edit the script before use.
  • Improved progress indicators now show percentage completed for each step.
  • Advanced logic determines the discrepancies in storage configuration between hosts. These potential configuration errors are displayed on screen with all relevant properties of the involved LUNs / Datastores!
  • Added support for Folders. Added menu choices that allow you to run the script against all VMHosts in a Folder or in a Cluster or even ALL VMHosts in your VC Server.

Get-StorageInfo (Rename to .ps1) Version 2

Test the script by adding a LUN to only one ESX server in a cluster. This misconfiguration (which will cause VMotion of a VM with files on that LUN to fail!) should be spotted by the script.

Questions? Comments? Leave a comment.

Shrink your scripts!

Carter Shanklin explains a great new feature of the official 1.0 release of the VI Toolkit here:

This should make your scripts (the ones created for the beta release) a lot shorter!

New-VM -vmHost (Get-VMHost $VMHostName) -datastore (Get-Datastore $DatastoreName) -network (Get-Network $NetworkName)


$VMHost = Get-VMHost $VMHostName
$Datastore = Get-Datastore $DatastoreName
$Network = Get-Network $NetworkName
New-VM -VMHost $VMHost -Datastore $Datastore -Network $Network


New-VM -VMHost $VMHostName -Datastore $DatastoreName -Network $NetworkName


Powershell Oneliner #4

Yesterday, alanrenouf asked the following question on the VMware Community VI Toolkit forums:

Is there a way (preferably a one-liner) to get a list of vm’s and the number of snapshots per vm?

Here’s a script that will get that info:

$VC = Connect-VIServer $VCServerName
$vms = Get-VM
$myCol = @()
ForEach ($vm in $vms)
  $snapshots = Get-Snapshot -VM $vm
  $myObj = "" | Select-Object VM, NumSnapshots
  $myObj.VM = $vm.name
  $myObj.NumSnapshots = ($snapshots | measure-object).count
  $myCol += $myObj
$myCol | Where-Object{$_.NumSnapshots -gt 0} | Sort-Object VM | Format-Table -AutoSize

And here’s a one-liner that does the same thing: 

Get-VM |
  Where{(Get-SnapShot -VM $_ | Measure-Object).Count -gt 0} |
  Format-Table Name, `
  @{Label="NumSnapshots";Expression={(Get-Snapshot -VM $_ | Measure-Object).Count}}