VMware Cloud Community
sp93
Contributor
Contributor

Way to report on Orphaned .VMDK files

I have looked in multiple locations, however aren't finding what I need. Many scripts will only report on clusters, or will also register the found VMDK files, which is what I don't want.

I would love (as I'm sure others would) to have a report in a .csv format that will scan my ESX 3.5 update 4 servers in my VC 2.5 update 4, and report any .VMDK files that aren't registered in VC.

We have iSCSI, storage as well as local storage being used on each server.

I have searched high and low for something, yet I can't seem to find anything that works.

thanks in advance.

Reply
0 Kudos
30 Replies
LucD
Leadership
Leadership

I started from the script in and made some, in my opinion, improvements.

*) used the disk layout from the VirtualMachine objects since this contains all the .VMDK files

*) included the .VMDK files from templates

*) optimised the search method by only looking for .VMDK files

*) changed the logic to determine if the .VMDK file is orphaned or not

*) exported the results to a CSV file

#
# Purpose : List all orphaned vmdk on all datastores in all VC's
# Version: 1.1
# Author  : HJA van Bokhoven
# Modifications: LucD

$arrayVC = <VC1-name>, <VC2-name>
$report = @()

foreach ($strVC in $arrayVC)
{
	Connect-VIServer $strVC 
	$arrUsedDisks = Get-View -ViewType VirtualMachine | % {$_.Layout} | % {$_.Disk} | % {$_.DiskFile}
	$arrDS = Get-Datastore | Sort-Object -property Name
	foreach ($strDatastore in $arrDS)
	{
		Write-Host $strDatastore.Name
		$ds = Get-Datastore -Name $strDatastore.Name | % {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.details = $fileQueryFlags
		$searchSpec.matchPattern = "*.vmdk"
		$searchSpec.sortFoldersFirst = $true
		$dsBrowser = Get-View $ds.browser
		$rootPath = ""
		$searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)

		foreach ($folder in $searchResult)
		{
			foreach ($fileResult in $folder.File)
			{
				if ($fileResult.Path)
				{
					if (-not ($arrUsedDisks -contains ($folder.FolderPath + $fileResult.Path))){
						$row = "" | Select DS, Path, File, Size, ModDate
						$row.DS = $strDatastore.Name
						$row.Path = $folder.FolderPath
						$row.File = $fileResult.Path
						$row.Size = $fileResult.FileSize
						$row.ModDate = $fileResult.Modification
						$report += $row
					} 
				}
			}
		} 
	} 
	# Disconnect session from VC
	disconnect-viserver -confirm:$false
}

$report | Export-Csv "C:\VMDK-orphaned.csv" -noTypeInformation

Please check if the files that are found by this script are indeed orphaned before deleting them !


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

Reply
0 Kudos
sp93
Contributor
Contributor

Thanks so much, the report seems correct, however my only issue is that the ESX server name isn't listed. So for the orphaned .vmdk files that sit on local storage, it's hard to locate what server they are actually on.

Is there anyway that the ESX server could be one of the columns?

thanks so much

Reply
0 Kudos
LucD
Leadership
Leadership

Sure, this should do the trick.

Note that if a datastore is shared between multiple ESX hosts you will see the name of the first ESX host in the CSV file.

#
# Purpose : List all orphaned vmdk on all datastores in all VC's
# Version: 1.1
# Author  : HJA van Bokhoven
# Modifications: LucD

$arrayVC = <VC1>,<VC2>
$report = @()

foreach ($strVC in $arrayVC)
{
	Connect-VIServer $strVC 
	$arrUsedDisks = Get-View -ViewType VirtualMachine | % {$_.Layout} | % {$_.Disk} | % {$_.DiskFile}
	$arrDS = Get-Datastore | Sort-Object -property Name
	foreach ($strDatastore in $arrDS)
	{
		Write-Host $strDatastore.Name
		$ds = Get-Datastore -Name $strDatastore.Name | % {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.details = $fileQueryFlags
		$searchSpec.matchPattern = "*.vmdk"
		$searchSpec.sortFoldersFirst = $true
		$dsBrowser = Get-View $ds.browser
		$rootPath = ""
		$searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)

		foreach ($folder in $searchResult)
		{
			foreach ($fileResult in $folder.File)
			{
				if ($fileResult.Path)
				{
					if (-not ($arrUsedDisks -contains ($folder.FolderPath + $fileResult.Path))){
						$row = "" | Select DS, Path, File, Size, ModDate, Host
						$row.DS = $strDatastore.Name
						$row.Path = $folder.FolderPath
						$row.File = $fileResult.Path
						$row.Size = $fileResult.FileSize
						$row.ModDate = $fileResult.Modification
						$row.Host = (Get-View $ds.Host[0].Key).Name
						$report += $row
					} 
				}
			}
		} 
	} 
	# Disconnect session from VC
	disconnect-viserver -confirm:$false
}

$report | Export-Csv "C:\VMDK-orphaned.csv" -noTypeInformation


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

Reply
0 Kudos
sp93
Contributor
Contributor

Awesome, thanks so much

Reply
0 Kudos
kimono
Expert
Expert

Any ideas why I get this error?

Exception calling "SearchDatastoreSubFolders" with "2" argument(s): "Invalid datastore path ''."

At 30 char:55

+ $searchResult = $dsBrowser.SearchDatastoreSubFolders &lt;&lt;&lt;&lt; ($rootPath, $searchSpec)

+ CategoryInfo : NotSpecified: (Smiley Happy [], MethodInvocationException

+ FullyQualifiedErrorId : DotNetMethodException

/kimono/
Reply
0 Kudos
LucD
Leadership
Leadership

Did you copy the script from your browser or did you use the attached file ?

The $rootPath variable contains some square brackets and the forum SW has problems with displaying those correctly.

Try the attached script.


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

Reply
0 Kudos
kimono
Expert
Expert

LucD,

Unfortunately that didn't work. Same error.

ta.

/kimono/
Reply
0 Kudos
kimono
Expert
Expert

HAHA yes it did fix it... stupid me, updated the script in a different folder to where my PS window was running it from.

thanks LucD.

/kimono/
Reply
0 Kudos
mdparker
Contributor
Contributor

Hi, Thanks for the Script. Unfortunately I cannot get it to work. I downloaded the attached script and all I did was modify the arrayvc line to look like this: $arrayVC = "vcentersrvr"

I keep getting this error:

Exception calling "SearchDatastoreSubFolders" with "2" argument(s): "Not initia

lized: boolean fileOwner"

At C:\Get-orphaned-VMDK.ps1:29 char:55

+ $searchResult = $dsBrowser.SearchDatastoreSubFolders &lt;&lt;&lt;&lt; ($rootPath,

$searchSpec)

+ CategoryInfo : NotSpecified: (Smiley Happy [], MethodInvocationException

+ FullyQualifiedErrorId : DotNetMethodException

Any thoughts? I am using vSphere 4. Thanks very much.

Mike

Reply
0 Kudos
LucD
Leadership
Leadership

The $arrayVC variable should be an array.

And if you want to create an array with only 1 element you should do

$arrayVC = @("vcentersrvr")

Try the script with that adaptation.


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

Reply
0 Kudos
mdparker
Contributor
Contributor

hmmm ...... I made the modification you suggested and I still get the exact same errors. I see that the script conncects to my VC and then begins pulling all the datastores, but the error is being displayed everytime DS is displayed on the screen. Any further thoughts? Thanks for the help. I'm very rusty in powershell.

Mike

Reply
0 Kudos
LucD
Leadership
Leadership

You're right, should have read your error message more accurately.

It seems that the FileQueryFlags object in vSphere has a new property called fileOwner.

This is a Boolean that needs to be set to $false or $true.

So these lines

...
		$fileQueryFlags = New-Object VMware.Vim.FileQueryFlags
		$fileQueryFlags.FileSize = $true
		$fileQueryFlags.FileType = $true
		$fileQueryFlags.Modification = $true
...

should be

...
		$fileQueryFlags = New-Object VMware.Vim.FileQueryFlags
               $fileQueryFlags.fileOwner = $true                   # Only for vSphere environments !
		$fileQueryFlags.FileSize = $true
		$fileQueryFlags.FileType = $true
		$fileQueryFlags.Modification = $true
...

when you run the script in a vSphere environment.


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

Reply
0 Kudos
mdparker
Contributor
Contributor

Sadly no luck. I copied your new lines and pasted them over the existing lines .... same error:

CX400_500GB_DS4

Exception calling "SearchDatastoreSubFolders" with "2" argument(s): "Not initia

lized: boolean fileOwner"

At C:\Get-orphaned-VMDK.ps1:30 char:55

+ $searchResult = $dsBrowser.SearchDatastoreSubFolders( <<<< $rootPath,

$searchSpec)

Thanks very much for the help!

Reply
0 Kudos
LucD
Leadership
Leadership

There's something fishy going on Smiley Sad

I could reproduce the problem with PowerCLI 4 in a vSphere environment.

@VMware Could this be a bug ?


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

Reply
0 Kudos
LucD
Leadership
Leadership

Carter confirms this is a bug, although it's not clear if it's a PowerCLI or a API bug.

The bypass is to leave out the details property completely.

In this script the details of the files (.vmdk) that are returned are not used in the script.

Attached a "vSphere" version of the script (with the "details" property left out).


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

Reply
0 Kudos
mdparker
Contributor
Contributor

The script runs without any runtime errors now and the output of the CSV file looks awesome. I could definitely see a use to schedule this once a Month as part of my health scripts, but sadly, there is still a couple of problems. All of the vmdk files show 0 in size and a ModDate of 1/1/0001 12:00:00 AM.

I appreciate you help very much and I hate to bother you more, but is there any chance you can dig a little deeper to resolve that issue?

Thanks very much.

Reply
0 Kudos
ykalchev
VMware Employee
VMware Employee

Hi,

All of the vmdk files show 0 in size and a ModDate of 1/1/0001 12:00:00 AM.

This is caused by the the bypass of the details property completely.

I've modified the script to workaround the bug LucD mentioned so I hope this will solve your task.

Regards,

Yasen

Yasen Kalchev, vSM Dev Team
Reply
0 Kudos
LucD
Leadership
Leadership

Thanks Yasen.

Where can we find more info on \[VMware.Vim.VIConvert\] ?


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

Reply
0 Kudos
mdparker
Contributor
Contributor

Awesome. Thank you both very much! It seems to work perfectly now. This will be very handy indeed.

Reply
0 Kudos