here is a script i put together to loop through the RVTools result and mount all the suspect VMDKs
$vCenterURL = "vmware server"
$ScriptFolder = "path to the script, output of the RVTools output CSV folder in here"
$RVToolsFolder = '' # name of the RVTools folder. leave black and the script will use the most recent.
$MountDisks = "no" # mount the disk to a test VM to confirm its safe to delete (ie not attached to anything)
$autoDeleteDisks = "no"
$TempVMName = "jase-orphVM"
if ($RVToolsFolder -eq '')
{
$bob = Get-ChildItem $ScriptFolder | where{$_.name -match "RVTools"} | select -last 1
$RVToolsFolder = $bob.name
}
connect-viserver $vCenterURL
# import the RVtools file and filter only the zombie vmdks
$RVToolsRaw = import-csv ($ScriptFolder + $RVToolsFolder + "\RVTools_tabvHealth.csv")
$RVOrphenDisks = $RVToolsRaw | where {$_.message -eq "Possibly a Zombie vmdk file! Please check."} | sort name
#
$OrphDisks = @()
$CurrentDS = "none"
$x = 0
do {
#
$tmpOrphDisk = '' | select Datastore,fullpath,path,date,sizeGB,Safe,removed
$tmpOrphDisk.Datastore = (((($RVOrphenDisks[$x].name).split("]"))[0]).replace("[","")).trim()
$tmpOrphDisk.path = ((($RVOrphenDisks[$x].name).split("]"))[1]).trim()
$tmpOrphDisk.fullpath = $RVOrphenDisks[$x].name
# if this file is not in the "current datastore" scan this datastore, get all vmdks and make it the current datastore.
# basically im expecting the RVTools list to be alphabetical so I dont have to rescan the same datastore more then once.
if ($CurrentDS -ne $tmpOrphDisk.Datastore)
{
$DS = get-datastore $tmpOrphDisk.Datastore
# scan the datastore and get all the vmdk details (path, mod date and size)
$DatastoreView = Get-View $DS.id # Create new search specification for SearchDatastoreSubFolders method
$SearchSpecification = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec # Create the file query flags to return Size, type and last modified
$fileQueryFlags = New-Object VMware.Vim.FileQueryFlags
$fileQueryFlags.FileSize = $true
$fileQueryFlags.Modification = $true # Set the flags on the search specification
$SearchSpecification.Details = $fileQueryFlags # Set the browser
$DatastoreBrowser = Get-View $DataStoreView.browser # Set root path to search from
$RootPath = (“[” + $tmpOrphDisk.Datastore + “]”) # Do the search
$DSscan = $DatastoreBrowser.SearchDatastoreSubFolders($RootPath, $SearchSpecification)
# loop through the list of vmdks and make it in in to searchable array
$DSDiskList = @()
foreach ($DFolder in $DSscan)
{
foreach ($Dfile in $DFolder.file)
{
if ($Dfile.path -like "*-flat.vmdk")
{
$tmpDSDiskList = '' | select path, date, size
$tmpDSDiskList.path = ($DFolder.Folderpath + ($Dfile.path).replace("-flat.vmdk",".vmdk"))
$tmpDSDiskList.date = $Dfile.Modification
$tmpDSDiskList.size = $Dfile.FileSize
$DSDiskList += $tmpDSDiskList
}
}
}
$CurrentDS = $tmpOrphDisk.Datastore
}
#
# populate report array with vmdk info
$diskResult = $DSDiskList | where{$_.path -eq $RVOrphenDisks[$x].name}
$tmpOrphDisk.date = $diskResult.date
$tmpOrphDisk.SizeGB = $diskResult.size / 1gb
if ($MountDisks -eq "yes")
{
# check the existance of the tmp test vm, create if need to
if (!(get-vm $tempVMname))
{
# create new VM and remove its disk and NIC
$TargetHost = get-vmhost -Datastore $tmpOrphDisk.Datastore | where {$_.connectionState -eq "Connected"} | select -First 1
New-VM -Name $tempVMname -Datastore $tmpOrphDisk.Datastore -vmhost $TargetHost
get-vm $tempVMname | Get-NetworkAdapter | Remove-NetworkAdapter -confirm:$false
get-vm $tempVMname | Get-HardDisk | Remove-HardDisk -DeletePermanently -confirm:$false
}
# check the existance of the tmp test vm
if (get-vm $tempVMname)
{
# get the first host that can access that datastore this orphan is on, move hte tmp VM to it
$TargetHost = get-vmhost -Datastore $tmpOrphDisk.Datastore | where {$_.connectionState -eq "Connected"} | select -First 1
get-vm $tempVMname | move-vm -destination $TargetHost
# mount the orphen vmdk to the tmp VM
write-host (" mounting " + $tmpOrphDisk.fullpath) -ForegroundColor Yellow
get-vm $tempVMname | New-HardDisk -DiskPath $tmpOrphDisk.fullpath
if ($?)
{
$tmpOrphDisk.Safe = "yes"
if ($autoDeleteDisks -eq "yes")
{
write-host (" removing " + $tmpOrphDisk.fullpath) -ForegroundColor Yellow
get-vm $tempVMname | Get-HardDisk | Remove-HardDisk -DeletePermanently -confirm:$false -WhatIf
if ($?)
{
write-host (" removed " + $tmpOrphDisk.fullpath) -ForegroundColor Yellow
$tmpOrphDisk.removed = "yes"
}else{
write-host (" remove failed " + $tmpOrphDisk.fullpath) -ForegroundColor red
$tmpOrphDisk.removed = "no"
}
}else{
# not allowed to delete disks
$tmpOrphDisk.removed = "disabled"
# detaching the disk from the tmpTest VM with out deleting the VMDK
write-host (" detaching " + $tmpOrphDisk.fullpath) -ForegroundColor Yellow
get-vm $tempVMname | Get-HardDisk | Remove-HardDisk -confirm:$false
}
}else{
# failed to mount vmdk
write-host (" mounting failed " + $tmpOrphDisk.fullpath) -ForegroundColor red
$tmpOrphDisk.Safe = "no"
}
}else{
# tmpTest VM not found, cant continue.
$tmpOrphDisk.removed = "no"
$tmpOrphDisk.Safe = "unknown"
}
}
$OrphDisks += $tmpOrphDisk
$x ++
} until($x -ge $RVOrphenDisks.count)
# remove the tmptest VM
get-vm $tempVMname | Get-HardDisk | Remove-HardDisk -confirm:$false
get-vm $tempVMname | remove-vm -Confirm:$false
$OrphDisks | Out-GridView
$OrphDisks | export-csv "Orphan_report.csv" -NoTypeInformation