#
# Purpose : List all orphaned vmdk on all datastores in all VC's
# Version: 1.1
# Author : HJA van Bokhoven
# Modified: Search multiple vDatacenters + Added code to make vmdk comparison better
#
#Timer
$scriptStartDate = get-date
#Main
$SearchDatacenter = "XXXX" #change to your datacenter name
$arrayVC = "XXXX.com" #change to your vCenter Server
$dtTime = get-date -UFormat "%Y%m%d_%H%M%S"
$strOutfile = "C:\tmp\vmware\find_orphaned_vmdks_${dtTime}.csv"
$Col = @()
Foreach ($strVC in $arrayVC)
{
Connect-VIServer $strVC
# $arrUsedDisks = Get-VM | Get-HardDisk | %{$_.filename}
$arrUsedDisks = Get-datacenter $SearchDatacenter | Get-VM | Get-HardDisk | %{ ($_.filename).ToLower() }
"<<<<<<<<<<<<<<<<<<"
#$arrUsedDisks
$arrUsedDisks|measure-object
"<<<<<<<<<<<<<<<<<<"
#exit
#DEBUG
#$arrUsedDisks | measure-object
#$arrUsedDisks
#echo " "
#
#...
#[LUN-name] VM-name/VM-name.vmdk
#[LUN-name] VM-name/VM-name.vmdk
#...
$arrDS = Get-datacenter $SearchDatacenter | get-vmhost | Get-Datastore
Foreach ($strDatastore in $arrDS)
{
$strDatastoreName = $strDatastore.name
"------------------------------"
$strDatastoreName
"------------------------------"
$ds = Get-Datastore -Name $strDatastoreName | %{Get-View $_.Id}
$fileQueryFlags = New-Object VMware.Vim.FileQueryFlags
$fileQueryFlags.FileSize = $true
$fileQueryFlags.FileType = $true
$fileQueryFlags.Modification = $true
$searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpec.searchCaseInsensitive = $True # DREF:we want case INsensitive search
$searchSpec.matchPattern = @("*.vmdk", "*.vrb") # DREF:find only these filetypes
$searchSpec.details = $fileQueryFlags
# $searchSpec.sortFoldersFirst = $true
#"##############################"
#$ds|measure-object
#"##############################"
$ds | % {
$thisDS = $_
$dsBrowser = Get-View $thisDS.browser
# $dsBrowser = Get-View $thisDS.MoRef
# $dsBrowser = Get-View -ViewType Datastore -VIObject $thisDS.MoRef
$rootPath = "["+$thisDS.summary.Name+"]"
$searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)
$myCol = @()
foreach ($folder in $searchResult)
{
$thisfolder = $folder.FolderPath # [LUN-name] VM-name/
foreach ($fileResult in $folder.File)
{
$file = "" | select Name, FullPath
$file.Name = $fileResult.Path
$strFilename = $file.Name
if ($strFilename) {
if (!$strFilename.Contains("-flat.vmdk") -AND !$strFilename.Contains("delta.vmdk") -AND !$strFilename.Contains("ctk.vmdk") -AND !$strFilename.Contains("-000"))
#flat files arent linked to directly in .vmx, and dont find delta files, and dont find CTK files, and dont find snapshot files
{
$strCheckfile = "*"+$file.Name+"*"
$realpath = ($thisfolder + "" + $strFilename).ToLower()
if ($arrUsedDisks -NotContains $realpath) {
Write-Host -BackgroundColor Red -ForegroundColor White "ORPHAN!`t${realpath}"
$this = "" | select VC,SearchCluster,OrphanVMDK,ModifiedDaysAgo,SizeGB
$now = (Get-Date)
$then = ([datetime] $fileResult.Modification)
$fileage = ($now-$then).Days
$filesizeGB = [int](($fileResult.FileSize)/1024/1024/1024)
$this.VC = $strVC
$this.SearchCluster = $SearchCluster
$this.OrphanVMDK = $realpath
$this.ModifiedDaysAgo = ${fileage}
$this.SizeGB = ${filesizeGB}
$Col+=$this
# $strOutput = "Orphaned VMDK Found: "+ $realpath + " `tFileModifiedDaysAgo: ${fileage} `tFileSizeGB: ${filesizeGB}"
# $strOutput
}
else {
Write-Host -BackgroundColor Green -ForegroundColor Black "IsFine!`t${realpath}"
}
}
}
}
}
}
}
}
#Timer
$scriptStopDate = get-date
echo ($scriptStartDate).date
echo ($scriptStopDate).date
$Col | sort VC,OrphanVMDK,ModifiedDaysAgo,SizeGB | ConvertTo-Csv -NoTypeInformation | Out-File $strOutfile