VMware Cloud Community
eparedesl
Contributor
Contributor

zombies o archivos sin uso

Estimados,

Alguien conoce algún scripts de como encontrar archivos huerfanos, zombies, carpetas sin uso, osea limpiar mis datastore de todos los archivos sin uso.

Nota: estoy utilizando rvtools, pero solo me muestra los .vmkd

0 Kudos
22 Replies
LucD
Leadership
Leadership

Sorry for replying in English.
You might want to have a look at my Orphaned Files And Folders – Spring Cleaning post


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

0 Kudos
eparedesl
Contributor
Contributor

Hola como ejecuto el script, se debe modificar?

Se ejecuta con powercli?

Me debo conectar al vcenter por powercli?

0 Kudos
LucD
Leadership
Leadership

Yes, the script is a PowerShell function, just copy it to a .ps1 file.
And yes, the function requires PowerCLI to be installed.

In the .ps1 file, after the function, add a Connect-VIServer.
Then on the next line call the Remove-OrpahedData function, you have to provide a datastore as a parameter.

Then call it all by typing the name of the .ps1 file at the PSprompt.


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

0 Kudos
eparedesl
Contributor
Contributor

La linea de conexión la agrego aquí, lo otro donde ingreso los datastore en que linea?:

Connect-VIServer -Server 10.1x.x.xx -Protocol https -User xx\xx -Password xxxx$

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)

}

}

}

}

}

}

}

}

}

0 Kudos
LucD
Leadership
Leadership

At the end of the file where you copied all this, you have to call the function.

For example with a line like

Remove-OrphanedData -Datastore MyDS

Add a line like this at the end of the file.


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

0 Kudos
eparedesl
Contributor
Contributor

Así debe quedar, lo marque en rojo?

Connect-VIServer -Server 10.1x.x.xx -Protocol https -User xx\xx -Password xxxx$

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 Datastore-1

.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)

}

}

Remove-OrphanedData -Datastore Datastore-1

}

}

}

}

}

}

0 Kudos
LucD
Leadership
Leadership

No, the call to the function should go behind the function definition, meaning after the last brace of the function.
Just make it the last line in the .ps1 file


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

0 Kudos
eparedesl
Contributor
Contributor

Algo así?

Connect-VIServer -Server 10.1x.x.xx -Protocol https -User xx\xx -Password xxxx$

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 Datastore-1

.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)

}

}

Remove-OrphanedData -Datastore Datastore-1

}

}

}

}

}

}

}

}

}

Remove-OrphanedData -Datastore Datastore-1

0 Kudos
LucD
Leadership
Leadership

Yes


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

0 Kudos
eparedesl
Contributor
Contributor

Una duda este scripts borra los huérfanos o solo me lista los posibles huérfanos para ser borrados?

Mi idea es solamente que me genere una lista de los posibles huérfanos, ideal seria a un txt o excel.

0 Kudos
eparedesl
Contributor
Contributor

El scritps borra automáticamente los huerfanos?

0 Kudos
LucD
Leadership
Leadership

No, you have to use the Delete switch with the $true value.
By default, nothing is erased.
See also the Sample Usage in my blog post I mentioned earlier.


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

0 Kudos
eparedesl
Contributor
Contributor

Para exportar a un CSV, se usa así?

Connect-VIServer -Server 10.1x.x.xx -Protocol https -User xx\xx -Password xxxx$

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)

}

}

}

}

}

}

}

}

}

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

0 Kudos
LucD
Leadership
Leadership

Yes


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

0 Kudos
eparedesl
Contributor
Contributor

Excelente, me funciono.

Existe alguna forma de averiguar, otros tipos de archivos que no sean .vmdk o carpetas que no estén en uso?

0 Kudos
eparedesl
Contributor
Contributor

Esto me arrojo:

PowerCLI C:\> Remove-OrphanedData -Datastore_IBM_1 | Export-Csv report.csv -NoTypeInformation -UseCulture

Remove-OrphanedData : No se encuentra ningún parámetro que coincida con el nombre del parámetro 'Datastore_IBM_1'.

En línea: 1 Carácter: 21

+ Remove-OrphanedData -Datastore_IBM_1 | Export-Csv report.csv -NoTypeI ...

+                     ~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Remove-OrphanedData], ParameterBindingException

    + FullyQualifiedErrorId : NamedParameterNotFound,Remove-OrphanedData

0 Kudos
LucD
Leadership
Leadership

In theory yes, but I don't have a script for that I'm afraid.


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

0 Kudos
LucD
Leadership
Leadership

You have to provide the Datastore parameter with the name of the datastore.

If your datastore is named Datastore_IBM_1, you would call the function like this

Remove-OrphanedData -Datastore Datastore_IBM_1


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

0 Kudos
eparedesl
Contributor
Contributor

gracias, funciono.

0 Kudos