How to search for all VMX files in all datastores and register them into VC ?

001function Register-VMX {
002  param($entityName = $null,$dsNames = $null,$template = $false,$ignore = $null,$checkNFS = $false,$whatif=$false)
003  
004  function Get-Usage{
005    Write-Host "Parameters incorrect" -ForegroundColor red
006    Write-Host "Register-VMX -entityName  -dsNames [,...]"
007    Write-Host "entityName   : a cluster-, datacenter or ESX hostname (not together with -dsNames)"
008    Write-Host "dsNames      : one or more datastorename names (not together with -entityName)"
009    Write-Host "ignore       : names of folders that shouldn't be checked"
010    Write-Host "template     : register guests ($false)or templates ($true) - default : $false"
011    Write-Host "checkNFS     : include NFS datastores - default : $false"
012    Write-Host "whatif       : when $true will only list and not execute - default : $false"
013  }
014  
015  if(($entityName -ne $null -and $dsNames -ne $null) -or ($entityName -eq $null -and $dsNames -eq $null)){
016    Get-Usage
017    break
018  }
019  
020  if($dsNames -eq $null){
021    switch((Get-Inventory -Name $entityName).GetType().Name.Replace("Wrapper","")){
022      "Cluster"{
023        $dsNames = Get-Cluster -Name $entityName | Get-VMHost | Get-Datastore | where {$_.Type -eq "VMFS" -or $checkNFS} | % {$_.Name}
024      }
025      "Datacenter"{
026        $dsNames = Get-Datacenter -Name $entityName | Get-Datastore | where {$_.Type -eq "VMFS" -or $checkNFS} | % {$_.Name}
027      }
028      "VMHost"{
029        $dsNames = Get-VMHost -Name $entityName | Get-Datastore | where {$_.Type -eq "VMFS" -or $checkNFS} | % {$_.Name}
030      }
031      Default{
032        Get-Usage
033        exit
034      }
035    }
036  }
037  else{
038    $dsNames = Get-Datastore -Name $dsNames | where {$_.Type -eq "VMFS" -or $checkNFS} | Select -Unique | % {$_.Name}
039  }
040  
041  $dsNames = $dsNames | Sort-Object
042  $pattern = "*.vmx"
043  if($template){
044    $pattern = "*.vmtx"
045  }
046  
047  foreach($dsName in $dsNames){
048    Write-Host "Checking " -NoNewline; Write-Host -ForegroundColor red -BackgroundColor yellow $dsName
049    $ds = Get-Datastore $dsName | Select -Unique | Get-View
050    $dsBrowser = Get-View $ds.Browser
051    $dc = Get-View $ds.Parent
052    while($dc.MoRef.Type -ne "Datacenter"){
053      $dc = Get-View $dc.Parent
054    }
055    $tgtfolder = Get-View $dc.VmFolder
056    $esx = Get-View $ds.Host[0].Key
057    $pool = Get-View (Get-View $esx.Parent).ResourcePool
058  
059    $vms = @()
060    foreach($vmImpl in $ds.Vm){
061      $vm = Get-View $vmImpl
062      $vms += $vm.Config.Files.VmPathName
063    }
064    $datastorepath = "[" + $ds.Name + "]"
065  
066    $searchspec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
067    $searchspec.MatchPattern = $pattern
068  
069    $taskMoRef = $dsBrowser.SearchDatastoreSubFolders_Task($datastorePath, $searchSpec)
070  
071    $task = Get-View $taskMoRef
072    while ("running","queued" -contains $task.Info.State){
073      $task.UpdateViewData("Info.State")
074    }
075    $task.UpdateViewData("Info.Result")
076    foreach ($folder in $task.Info.Result){
077      if(!($ignore -and (&{$res = $false; $folder.FolderPath.Split("]")[1].Trim(" /").Split("/") | %{$res = $res -or ($ignore -contains $_)}; $res}))){
078        $found = $FALSE
079        if($folder.file -ne $null){
080          foreach($vmx in $vms){
081            if(($folder.FolderPath + $folder.File[0].Path) -eq $vmx){
082              $found = $TRUE
083            }
084          }
085          if (-not $found){
086            if($folder.FolderPath[-1] -ne "/"){$folder.FolderPath += "/"}
087            $vmx = $folder.FolderPath + $folder.File[0].Path
088            if($template){
089              $params = @($vmx,$null,$true,$null,$esx.MoRef)
090            }
091            else{
092              $params = @($vmx,$null,$false,$pool.MoRef,$null)
093            }
094            if(!$whatif){
095              $taskMoRef = $tgtfolder.GetType().GetMethod("RegisterVM_Task").Invoke($tgtfolder, $params)
096              Write-Host "`t" $vmx "registered"
097            }
098            else{
099              Write-Host "`t" $vmx "registered" -NoNewline; Write-Host -ForegroundColor blue -BackgroundColor white " ==> What If"
100            }
101          }
102        }
103      }
104    }
105    Write-Host "Done"
106  }
107}
108  
109# Register-VMX -entityName "MyDatacenter"
110# Register-VMX -dsNames "datastore1","datastore2"
111# Register-VMX -dsNames "datastore1","datastore2" -template:$true
112# Register-VMX -entityName "MyDatacenter" -ignore "SomeFolder"
113# Register-VMX -dsNames "datastore3","datastore4" -ignore "SomeFolder" -checkNFS:$true
114# Register-VMX -entityName "MyDatacenter" -whatif:$true

Annotations


Line 15: both parameters (entityName and dsNames) can not be used together.

Line 20-36: if an entityName was given the switch will retrieve the list of datastores.

Line 37-39: if dsNames was used add or remove NFS datastores (depending on the checkNFS switch)

Line 42-67: retrieval of the required parameters for the SearchDatastoreSubFolders_Task and RegisterVM_Task methods

Line 56: if the datastore is shared between several ESX/ESXi servers, the script will take the first server

Line 67-69: the VMConfigFileQuery seems to have a problem finding VMX files on some datastores. That’s why the script uses the MatchPattern property.

Line 71-74: this loop waits for the SearchDatastoreSubFolders_Task to finish. To make sure it looks at the actual value of the Result property, the script calls the UpdateViewData method.

Line 77: this line takes care of folders that should be ignored. Update 5: for nested folders, the script checks each folderpath qualifier against the -ignore parameter.

Line 86: when you’re connected to an ESX/ESXi host the FolderPath property doesn’t have a forward slash as the last character. This line corrects that.

Line 88-93: the RegisterVM_Task method needs different parameters if it is called for a guest or for a template

Line 88 & 91: the RegisterVM_Task method should use the DisplayName field from the VMX file for the name of the VM that will be registered. Unfortunately you can’t pass a $null value for a parameter that is defined as a String. This bypasses that limitation.

Line 94-100: these lines take care of the -whatif switch

Line 109-114: some sample calls to the Register-VMX function

Usage


The function Register-VMX can be called as follows

  1. With the -entityName parameter, where you can pass a datacentername, a clustername or an ESX hostname
    • Register-VMX -entityName “MyCluster”
    • Register-VMX -entityName “MyDatacenter”
    • Register-VMX -entityName “esx1.test.local”
  2. With the -dsNames parameter, where you can pass one or more datastorenames.
    • Register-VMX -dsNames “datastore1″
    • Register-VMX -dsNames “datastore1″,”datastore2″,”datastore3″
  3. With the -template parameter which allows you to specify if you want to register guests ($false) or templates ($true). The default is to register guests.
    • Register-VMX -dsNames “datastore1″,”datastore2″,”datastore3″ -template:$true
    • Register-VMX -entityName “MyCluster” -template:$false
  4. With the -ignore parameter which allows you to specify that scripts should not look in specific folders for unregistered VMX files. The default is to look in all folders.
    • Register-VMX -entityName “MyCluster” -ignore “Folder1″,”Folder2″
  5. With the -checkNFS switch which allows you to specify if NFS datastores should be checked as well. The default is to not check NFS datastores.
    • Register-VMX -entityName “MyCluster” -CheckNFS:$true
    • Register-VMX -dsNames “datastore1″,”datastore2″,”datastore3″ -CheckNFS:$true
  6. With the -whatif switch set to $true the script will only show the actions and not actually execute them. The default is $false, which means the found .VMX (or .VMTX) files will be registered.
    • Register-VMX -entityName “MyCluster” -whatif:$true

Comments

Popular Posts