There are quite a few clicks to add a virtual machine from a datastore to inventory. If you were to consolidate an environment and had to add multiple virtual machines this would be quite a manual task. Easier solution? Script it! The below script makes scanning a datastore and registering all virtual machines with vCenter a breeze.
You must have VMware PowerCLI installed in order to have the cmdlets required for PowerShell to run the script.
Add VMX (Virtual Machines) to Inventory from a Datastore:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
##################################################################### # Load VMware Plugins and vCenter Connect # ##################################################################### Add-PSSnapin vmware.vimautomation.core connect-viserver -server ENTER VCENTER FQDN HERE ##################################################################### # Add .VMX (Virtual Machines) to Inventory from Datastore # ##################################################################### # Variables: Update these to the match the environment $Cluster = "ENTER CLUSTER NAME HERE" $Datastore = "ENTER DATASTORE NAME HERE" $VMFolder = "ENTER FOLDER NAME HERE" $ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1 foreach($Datastore in $Datastore) { # Searches for .VMX Files in datastore variable $ds = Get-Datastore -Name $Datastore | %{Get-View $_.Id} $SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec $SearchSpec.matchpattern = "*.vmx" $dsBrowser = Get-View $ds.browser $DatastorePath = "[" + $ds.Summary.Name + "]" # Find all .VMX file paths in Datastore variable and filters out .snapshot $SearchResult = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | where {$_.FolderPath -notmatch ".snapshot"} | %{$_.FolderPath + ($_.File | select Path).Path} # Register all .VMX files with vCenter foreach($VMXFile in $SearchResult) { New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -RunAsync } } |
Let’s see it in action!
I want to scan my “Synology LUN” datastore and add any virtual machines it finds into the in the “_Script Testing” folder in the cluster named “Lab Cluster 01”.
I prefer to run my scripts out of PowerShell ISE as I feel it gives me more control. I updated the variables (highlighted in yellow) and ran it:
In the Tasks pane of the vSphere Client you will see failed tasks if the script finds virtual machines that are already in your inventory. The virtual machines that were not in my inventory are now in the “_Script Testing” folder:
Add VMX (Virtual Machines) to Inventory from a Datastore Cluster:
The $Datastores variable can be changed to scan a Datastore Cluster instead of specific ones:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
##################################################################### # Load VMware Plugins and vCenter Connect # ##################################################################### Add-PSSnapin vmware.vimautomation.core connect-viserver -server ENTER VCENTER FQDN HERE ##################################################################### # Add .VMX (Virtual Machines) to Inventory from Storage Cluster # ##################################################################### # Variables: Update these to the match the environment $Cluster = "ENTER CLUSTER NAME HERE" $Datastores = get-datastorecluster "ENTER DATASTORE CLUSTER NAME HERE" | get-datastore $VMFolder = "ENTER FOLDER NAME HERE" $ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1 foreach($Datastores in $Datastores) { # Set up Search for .VMX Files in Datastore Cluster $ds = Get-Datastore -Name $Datastores | %{Get-View $_.Id} $SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec $SearchSpec.matchpattern = "*.vmx" $dsBrowser = Get-View $ds.browser $DatastorePath = "[" + $ds.Summary.Name + "]" # Find all .VMX file paths in Datastore variable and filters out .snapshot $SearchResult = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | where {$_.FolderPath -notmatch ".snapshot"} | %{$_.FolderPath + ($_.File | select Path).Path} # Register all .VMX files with vCenter foreach($VMXFile in $SearchResult) { New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -RunAsync } } |
I updated the highlighted variables:
I hope this helps speed up the process if you find yourself in a situation needing to scan and add multiple VMs to inventory!
Hi there, Though its quite an old post…but i was trying to use this script in my environment and I am getting below error
=================================================================================================
Exception calling “SearchDatastoreSubFolders” with “2” argument(s): “Invalid datastore path ‘[DataStore1 DataStore1 DataStore1 DataStore1]’.”
At C:\Users\Administrator\Desktop\Automation Scripts\Inventory.ps1:27 char:1
+ $SearchResult = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException
-=================================================================================================
It does not like your $Datastores variable, is the DataStore1 in a Storage Cluster? You can edit the $Datastores variable to select a specific datastore like this:
$Datastores = “DataStore1”
I ran into a similar issue and it was because in my entire vcenter, which spans MANY datacenters, there was more than one storage LUN with the same name.
How are you getting Get-View (line 23) to run without a VIObject argument? Thats where the scripts dies for me…
Line 23 narrows down the data from what Line 20 created. I had the variable incorrect, it was $Datastores and should have been $Datastore (without the s). Remove that s and try again
Hi i have an issue in case of multiple vmdk for a vm not on same directory as vmx file, is there a way to resolve path for all vmdk properly ?
Hi Daniel,
thank you for sharing this.
I have difficulties on understanding why you add this line of code
%{$_.FolderPath + ($_.File | select Path).Path}
Why you used a “where” clause and then you did not compare anything?
Hope you can help
Regards