VMware Cloud Community
Kumargtk
Contributor
Contributor

How to find Orphaned VMDK files

How can we find out Orphaned VMDK files in all the Data-stores.

119 Replies
LucD
Leadership
Leadership

You could try the script from my Orphaned files and folders - Spring cleaning post.


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

Kumargtk
Contributor
Contributor

Hi Umesh,

This will exclude the Snapshots file right. i want to check for more than 50 servers. If u have any script... please help.

Reply
0 Kudos
johnbel1
Contributor
Contributor

Take a look at this post:

Virtually Jason: Deleting Orphaned (AKA Zombie) VMDK Files

I have found it works well for me.

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso

LucD ,

Just to confirm if the script that you created will not delete anything yet unless it is used with -Delete switch? Is it possible to list the result in .CSV file ?

function Remove-OrphanedData {

<#

.SYNOPSIS   Remove orphaned folders and VMDK files

.DESCRIPTION   The function searches orphaned folders and VMDK files

   on one or more datastores and reports its findings.

   Optionally the function removes  the orphaned folders   and VMDK files

.NOTES   Author:  Luc Dekens

.PARAMETER Datastore

   One or more datastores.

   The default is to investigate all shared VMFS datastores

.PARAMETER Delete

   A switch that indicates if you want to remove the folders

   and VMDK files

.EXAMPLE

   PS> Remove-OrphanedData -Datastore ds1

.EXAMPLE

  PS> Get-Datastore ds* | Remove-OrphanedData

.EXAMPLE

  PS> Remove-OrphanedData -Datastore $ds -Delete

#>

  [CmdletBinding(SupportsShouldProcess=$true)]

  param(

  [parameter(Mandatory=$true,ValueFromPipeline=$true)]

  [PSObject[]]$Datastore,

  [switch]$Delete

  )

  begin{

    $fldList = @{}

    $hdList = @{}

    $fileMgr = Get-View FileManager

  }

  process{

    foreach($ds in $Datastore){

      if($ds.GetType().Name -eq "String"){

        $ds = Get-Datastore -Name $ds

      }

      if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess){

        Get-VM -Datastore $ds | %{

          $_.Extensiondata.LayoutEx.File | where{"diskDescriptor","diskExtent" -contains $_.Type} | %{

            $fldList[$_.Name.Split('/')[0]] = $_.Name

            $hdList[$_.Name] = $_.Name

          }

        }

        Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{

          $_.Extensiondata.LayoutEx.File | where{"diskDescriptor","diskExtent" -contains $_.Type} | %{

            $fldList[$_.Name.Split('/')[0]] = $_.Name

            $hdList[$_.Name] = $_.Name

          }

        }

        $dc = $ds.Datacenter.Extensiondata

        $flags = New-Object VMware.Vim.FileQueryFlags

        $flags.FileSize = $true

        $flags.FileType = $true

        $disk = New-Object VMware.Vim.VmDiskFileQuery

        $disk.details = New-Object VMware.Vim.VmDiskFileQueryFlags

        $disk.details.capacityKb = $true

        $disk.details.diskExtents = $true

        $disk.details.diskType = $true

        $disk.details.thin = $true

        $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec

        $searchSpec.details = $flags

        $searchSpec.Query += $disk

        $searchSpec.sortFoldersFirst = $true

        $dsBrowser = Get-View $ds.ExtensionData.browser

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

        $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)

        foreach($folder in $searchResult){

          if($fldList.ContainsKey($folder.FolderPath.TrimEnd('/'))){

            foreach ($file in $folder.File){

              if(!$hdList.ContainsKey($folder.FolderPath + $file.Path)){

                New-Object PSObject -Property @{

                  Folder = $folder.FolderPath

                  Name = $file.Path

                  Size = $file.FileSize

                  CapacityKB = $file.CapacityKb

                  Thin = $file.Thin

                  Extents = [string]::Join(',',($file.DiskExtents))

                }

                if($Delete){

                  If ($PSCmdlet.ShouldProcess(($folder.FolderPath + " " + $file.Path),"Remove VMDK")){

                    $dsBrowser.DeleteFile($folder.FolderPath + $file.Path)

                  }

                }

              }

            }

          }

          elseif($folder.File | where {"cos.vmdk","esxconsole.vmdk" -notcontains $_.Path}){

            $folder.File | %{

              New-Object PSObject -Property @{

                Folder = $folder.FolderPath

                Name = $_.Path

                Size = $_.FileSize

                CapacityKB = $_.CapacityKB

                Thin = $_.Thin

                Extents = [String]::Join(',',($_.DiskExtents))

              }

            }

            if($Delete){

              if($folder.FolderPath -eq $rootPath){

                $folder.File | %{

                  If ($PSCmdlet.ShouldProcess(($folder.FolderPath + " " + $_.Path),"Remove VMDK")){

                    $dsBrowser.DeleteFile($folder.FolderPath + $_.Path)

                  }

                }

              }

              else{

                If ($PSCmdlet.ShouldProcess($folder.FolderPath,"Remove Folder")){

                  $fileMgr.DeleteDatastoreFile($folder.FolderPath,$dc.MoRef)

                }

              }

            }

          }

        }

      }

    }

  }

}

Thanks in advance.

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

Confirmed, without the Delete switch nothing will be removed.

The script shows the results on the console by default.

You can just pipe the result to a CSV.

Remove-OrphanedData -Datastore DS1 | Export-Csv report.csv -NoTypeInformation -UseCulture


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

AlbertWT
Virtuoso
Virtuoso

LucD ,

You are absolutely wonderful Smiley Happy.

Thanks for the script.

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso

Hi Luc,

What about executing the script to go through all of my VMFS datastore ?

I tried the below line:

Remove-OrphanedData -Datastore * | Export-Csv -Path "C:\TEMP\VMDKreport.csv" -NoTypeInformation -UseCulture

but somehow it doesn't work ?

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

Try like this

Get-Datastore | Remove-OrphanedData | Export-Csv report.csv -NoTypeInformation -UseCulture


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

AlbertWT
Virtuoso
Virtuoso

Yes, it works as expected.

Thanks once again Luc.

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
formz
Enthusiast
Enthusiast

Hey LucD, I'm trying to run this script but I'm not getting any data out of it.

I copy the function that is pasted in this thread, then after I put:

connect-viserver nameofmyvcenterhere

Remove-OrphanedData -Datastore SGINSCLSV01_DATASTORE1 | Export-Csv 'E:\report.csv' -NoTypeInformation -UseCulture

It runs without error, but just brings me back to the prompt and doesn't export a CSV at all. Any insight?

Thanks

Reply
0 Kudos
LucD
Leadership
Leadership

It could mean there are no orphaned VMDK on that datastore.

Can you do a test, create a VM and then unregister it?


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

formz
Enthusiast
Enthusiast

I know there are a lot. We have a program (Turbonomic) that shows orphaned VMDKs and has many in the list of that datastore, but I'm trying to get to a point where we don't have to rely on third party tools for the information.

EDIT: I should also mention that it returns to the prompt immediately - like it's not searching at all.

Reply
0 Kudos
LucD
Leadership
Leadership

The function only works for shared VMFS datastores.

Is your datastore a shared VMFS datastore?


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

formz
Enthusiast
Enthusiast

Ha! That's why... They're all NFS datastores. Am I screwed at this point?

Reply
0 Kudos
LucD
Leadership
Leadership

You can test with this

Get-Datastore -Name SGINSCLSV01_DATASTORE1 |

select Name,Type,@{N='Shared';E={$_.ExtensionData.Summary.MultipleHostAccess}}


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

Reply
0 Kudos
LucD
Leadership
Leadership

Try removing lines 42 and 124, in theory it should work for NFS datastores as well


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

Reply
0 Kudos
formz
Enthusiast
Enthusiast

Removing 42 and 124 worked perfectly! Thank you so much!

Reply
0 Kudos
rstack
Contributor
Contributor

Is there a way to exclude a directory? It works great for NFS with the modifications listed. But as we use a NetApp feature I would like to exclude the folder .snapshot/

Reply
0 Kudos
LucD
Leadership
Leadership

Yes, you could add a Where-clause on line 77


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

Reply
0 Kudos