VMware Cloud Community
BaluVirigineni
Enthusiast
Enthusiast

PowerCLI Script to list unregistered VMs in a datacenter

Can someone give me a PowerCLI Script to list unregistered VMs in a datacenter by scanning Datastores.

Reply
0 Kudos
15 Replies
RvdNieuwendijk
Leadership
Leadership

Take a look at Luc's blog post VMX Raiders Revisited | LucD notes.


The script in the blog post will also register the unregistered VM's. If you don't want to register the VM's you have to remove the lines 18, 19 and 20 from the script.

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
Reply
0 Kudos
BaluVirigineni
Enthusiast
Enthusiast

The one you mentioned is scanning cluster wise, I want to scan all the Datastores in a datacenter..can you provide script which do scan entire DC

Reply
0 Kudos
LucD
Leadership
Leadership

If you take the script from the original "Raiders" post, see Raiders of the Lost VMX, then you can use the WhatIf switch to only report on the unregistered VMX files.

No need to delete lines from the function.


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

Reply
0 Kudos
LucD
Leadership
Leadership

You can get all the datastores from the datacenter, and then call the function.

$ds = Get-Datacenter -Name MyDC | Get-Datastore | %{$_.Name}

Register-VMX -dsNames $ds -WhatIf


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

Reply
0 Kudos
RvdNieuwendijk
Leadership
Leadership

In the script from the original "Raiders of the lost VMX" post you can specify a datacenter as a value for the entityName parameter.

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
Reply
0 Kudos
BaluVirigineni
Enthusiast
Enthusiast

LucD,

I have given Datacenter Name for parameter "entityName" in the Raiders of the Lost VMX, script and run, will it give list of unregister VMs

Reply
0 Kudos
BaluVirigineni
Enthusiast
Enthusiast

Also I dont want the VMs to get registered, I just want the list of unregistered VMs, apart from the above modification do we need modification ..

Reply
0 Kudos
BaluVirigineni
Enthusiast
Enthusiast

function Register-VMX {

    param($entityName =$null,$dsNames = $null,$template = $false,$ignore = $null,$checkNFS = $false,$whatif=$false)

    function Get-Usage{

        Write-Host "Parameters incorrect" -ForegroundColor red

        Write-Host "Register-VMX -entityName  -dsNames [,...]"

       Write-Host "elab_Legacy"

        Write-Host "dsNames      : one or more datastorename names (not together with -entityName)"

        Write-Host "ignore       : names of folders that shouldn't be checked"

        Write-Host "template     : register guests ($false)or templates ($true) - default : $false"

        Write-Host "checkNFS     : include NFS datastores - default : $false"

        Write-Host "whatif       : when $true will only list and not execute - default : $false"

    }

    if(($entityName -ne $null -and $dsNames -ne $null) -or ($entityName -eq $null -and $dsNames -eq $null)){

        Get-Usage

        break

    }

    if($dsNames -eq $null){

        switch((Get-Inventory -Name $entityName).GetType().Name.Replace("Wrapper","")){

            "Cluster"{

                $dsNames = Get-Cluster -Name $entityName | Get-VMHost | Get-Datastore | where {$_.Type -eq "VMFS" -or $checkNFS}

| % {$_.Name}

            }

            "Datacenter"{

                $dsNames = Get-Datacenter -Name $entityName | Get-Datastore | where {$_.Type -eq "VMFS" -or $checkNFS} | %

{$_.Name}

            }

            "VMHost"{

                $dsNames = Get-VMHost -Name $entityName | Get-Datastore | where {$_.Type -eq "VMFS" -or $checkNFS} | % {$_.Name}

            }

            Default{

                Get-Usage

                exit

            }

        }

    }

    else{

        $dsNames = Get-Datastore -Name $dsNames | where {$_.Type -eq "VMFS" -or $checkNFS} | Select -Unique | % {$_.Name}

    }

    $dsNames = $dsNames | Sort-Object

    $pattern = "*.vmx"

    if($template){

        $pattern = "*.vmtx"

    }

    foreach($dsName in $dsNames){

        Write-Host "Checking " -NoNewline; Write-Host -ForegroundColor red -BackgroundColor yellow $dsName

        $ds = Get-Datastore $dsName | Select -Unique | Get-View

        $dsBrowser = Get-View $ds.Browser

        $dc = Get-View $ds.Parent

        while($dc.MoRef.Type -ne "Datacenter"){

            $dc = Get-View $dc.Parent

        }

        $tgtfolder = Get-View $dc.VmFolder

        $esx = Get-View $ds.Host[0].Key

        $pool = Get-View (Get-View $esx.Parent).ResourcePool

        $vms = @()

        foreach($vmImpl in $ds.Vm){

            $vm = Get-View $vmImpl

            $vms += $vm.Config.Files.VmPathName

        }

        $datastorepath = "[" + $ds.Name + "]"

        $searchspec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec

        $searchspec.MatchPattern = $pattern

        $taskMoRef = $dsBrowser.SearchDatastoreSubFolders_Task($datastorePath, $searchSpec)

        $task = Get-View $taskMoRef

        while ("running","queued" -contains $task.Info.State){

            $task.UpdateViewData("Info.State")

        }

        $task.UpdateViewData("Info.Result")

        foreach ($folder in $task.Info.Result){

            if(!($ignore -and (&{$res = $false; $folder.FolderPath.Split("]")[1].Trim(" /").Split("/") | %{$res = $res -or ($ignore

-contains $_)}; $res}))){

                $found = $FALSE

                if($folder.file -ne $null){

                    foreach($vmx in $vms){

                        if(($folder.FolderPath + $folder.File[0].Path) -eq $vmx){

                            $found = $TRUE

                        }

                    }

                    if (-not $found){

                        if($folder.FolderPath[-1] -ne "/"){$folder.FolderPath += "/"}

                        $vmx = $folder.FolderPath + $folder.File[0].Path

                        if($template){

                            $params = @($vmx,$null,$true,$null,$esx.MoRef)

                        }

                        else{

                            $params = @($vmx,$null,$false,$pool.MoRef,$null)

                        }

                        if(!$whatif){

                            $taskMoRef = $tgtfolder.GetType().GetMethod("RegisterVM_Task").Invoke($tgtfolder,

$params)

                            Write-Host "`t" $vmx "registered"

                        }

                        else{

                            Write-Host "`t" $vmx "registered" -NoNewline; Write-Host -ForegroundColor blue -

BackgroundColor white " ==> What If"

                        }

                    }

                }

            }

        }

        Write-Host "Done"

    }

}

# Register-VMX -entityName "MyDatacenter"

# Register-VMX -dsNames "datastore1","datastore2"

# Register-VMX -dsNames "datastore1","datastore2" -template:$true

# Register-VMX -entityName "MyDatacenter" -ignore "SomeFolder"

# Register-VMX -dsNames "datastore3","datastore4" -ignore "SomeFolder" -checkNFS:$true

# Register-VMX -entityName "MyDatacenter" -whatif:$true

I have given datacneter name for entityName as mentioned above, its been highlighted too in the script. Now will the above script gives the list of unregisterd VMs after running.

Reply
0 Kudos
LucD
Leadership
Leadership

You will have to uncomment that line.

Register-VMX -entityName "MyDatacenter" -WhatIf

Btw, what is this line doing in the function ?

Write-Host "elab_Legacy"


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

Reply
0 Kudos
BaluVirigineni
Enthusiast
Enthusiast

Oh ok, I thought Script will take input from Write-Host cmdlet, I have uncommented line Register-VMX -entityName...LucD I dont want the VMs to be registered back to vcenter, I just want the list of Unregistered VMs so will the below script do the same need.

function 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

Reply
0 Kudos
LucD
Leadership
Leadership

Make sure to add the WhatIf switch (see my previous answer).


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

BaluVirigineni
Enthusiast
Enthusiast

Thanks LucD i got what you mentioned, thanks for such a detail explanation.

Reply
0 Kudos
LucD
Leadership
Leadership

You're welcome.


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

Reply
0 Kudos
BaluVirigineni
Enthusiast
Enthusiast

LucD can you help me in taking the output to a  text file, because we have lot of datastores in the Dataceneter. It will take lot of time to look at the output of the script.

Reply
0 Kudos
LucD
Leadership
Leadership

Not 100% sure I get the question, but if you just want to save the output in a file, one of the ways of doing that could be

Start-Transcript C:\report.txt

Register-VMX -entityName "MyDatacenter" -WhatIf

Stop-Transcript

The reason is use the Transcript cmdlet, is because the function uses the Write-Host cmdlet which writes directly to the screen.

The output of Write-Host can not be redirected or piped to one of the Out- cmdlets.

I know, this is one of my early scripts, when I didn't know or followed several of the PowerShell best practices :smileygrin:


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

Reply
0 Kudos