<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>datastore Archives - LucD notes</title>
	<atom:link href="https://www.lucd.info/tag/datastore/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.lucd.info/tag/datastore/</link>
	<description>My PowerShell ramblings</description>
	<lastBuildDate>Wed, 08 Apr 2020 11:02:08 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://www.lucd.info/wp-content/uploads/2018/12/cropped-120px-Tibetan_Dharmacakra-32x32.png</url>
	<title>datastore Archives - LucD notes</title>
	<link>https://www.lucd.info/tag/datastore/</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/><atom:link rel="hub" href="https://websubhub.com/hub"/>	<item>
		<title>Orphaned Files Revisited</title>
		<link>https://www.lucd.info/2016/09/13/orphaned-files-revisited/</link>
					<comments>https://www.lucd.info/2016/09/13/orphaned-files-revisited/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Tue, 13 Sep 2016 18:52:11 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[Orphan]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[report]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[orphan]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[revisited]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=5384</guid>

					<description><![CDATA[In my Orphaned files and folders – Spring cleaning post from way back, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In my <a href="https://www.lucd.info/2011/04/25/orphaned-files-and-folders-spring-cleaning/" target="_blank" rel="noopener noreferrer">Orphaned files and folders – Spring cleaning</a> post from way back, I provided a script to find orphaned VMDKs. This week there was a <a href="https://communities.vmware.com/message/2619238#2619238" target="_blank" rel="noopener noreferrer">post</a> in the <a href="https://communities.vmware.com/community/vmtn/automationtools/powercli" target="_blank" rel="noopener noreferrer">VMTN PowerCLI Community</a> that had a request to find <span style="text-decoration: underline;">all</span> orphaned files. Time for a revisit of my old post!</p>
<p style="padding-left: 30px;"><a href="https://www.lucd.info/2016/09/13/orphaned-files-revisited/file-orphan/" rel="attachment wp-att-5388"><img fetchpriority="high" decoding="async" class="alignnone wp-image-5388 size-medium" src="https://lucd.info/wp-content/uploads/2016/09/file-orphan-300x205.png" alt="file-orphan" width="300" height="205" srcset="https://www.lucd.info/wp-content/uploads/2016/09/file-orphan-300x205.png 300w, https://www.lucd.info/wp-content/uploads/2016/09/file-orphan.png 425w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>I took my old script, massaged it a bit and gave it a more contemporary look and feel.<br />
Just for info, the <a href="https://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreBrowser.html#searchSubFolders" target="_blank" rel="noopener noreferrer">SearchDatastoreSubFolders</a> method is relatively slow. So scanning a couple of datastores for orphaned files might take a bit of time. Be patient <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><span id="more-5384"></span></p>
<h2>The Script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-VmwOrphan{
&lt;#
.SYNOPSIS
  Find orphaned files on a datastore
.DESCRIPTION
  This function will scan the complete content of a datastore.
  It will then verify all registered VMs and Templates on that
  datastore, and compare those files with the datastore list.
  Files that are not present in a VM or Template are considered
  orphaned
.NOTES
  Author:  Luc Dekens
.PARAMETER Datastore
  The datastore that needs to be scanned
.EXAMPLE
  PS&gt; Get-VmwOrphan -Datastore DS1
.EXAMPLE
  PS&gt; Get-Datastore -Name DS* | Get-VmwOrphan
#&gt;

  [CmdletBinding()]
  param(
    [parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [PSObject[]]$Datastore
  )
  
  Begin{
    $flags = New-Object VMware.Vim.FileQueryFlags
    $flags.FileOwner = $true
    $flags.FileSize = $true
    $flags.FileType = $true
    $flags.Modification = $true
    
    $qFloppy = New-Object VMware.Vim.FloppyImageFileQuery
    $qFolder = New-Object VMware.Vim.FolderFileQuery
    $qISO = New-Object VMware.Vim.IsoImageFileQuery
    $qConfig = New-Object VMware.Vim.VmConfigFileQuery
    $qConfig.Details = New-Object VMware.Vim.VmConfigFileQueryFlags
    $qConfig.Details.ConfigVersion = $true
    $qTemplate = New-Object VMware.Vim.TemplateConfigFileQuery
    $qTemplate.Details = New-Object VMware.Vim.VmConfigFileQueryFlags
    $qTemplate.Details.ConfigVersion = $true
    $qDisk = New-Object VMware.Vim.VmDiskFileQuery
    $qDisk.Details = New-Object VMware.Vim.VmDiskFileQueryFlags
    $qDisk.Details.CapacityKB = $true
    $qDisk.Details.DiskExtents = $true
    $qDisk.Details.DiskType = $true
    $qDisk.Details.HardwareVersion = $true
    $qDisk.Details.Thin = $true
    $qLog = New-Object VMware.Vim.VmLogFileQuery
    $qRAM = New-Object VMware.Vim.VmNvramFileQuery
    $qSnap = New-Object VMware.Vim.VmSnapshotFileQuery
    
    $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
    $searchSpec.details = $flags
    $searchSpec.Query = $qFloppy,$qFolder,$qISO,$qConfig,$qTemplate,$qDisk,$qLog,$qRAM,$qSnap
    $searchSpec.sortFoldersFirst = $true
  }
  
  Process{
    foreach($ds in $Datastore){
      if($ds.GetType().Name -eq "String"){
        $ds = Get-Datastore -Name $ds
      }

# Only shared VMFS datastore
      if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess -and $ds.State -eq 'Available'){
        Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tLooking at $($ds.Name)"
  
# Define file DB
        $fileTab = @{}

# Get datastore files
        $dsBrowser = Get-View -Id $ds.ExtensionData.browser
        $rootPath = "[" + $ds.Name + "]"
        $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec) | Sort-Object -Property {$_.FolderPath.Length}
        foreach($folder in $searchResult){
          foreach ($file in $folder.File){
            $key = "$($folder.FolderPath)$(if($folder.FolderPath[-1] -eq ']'){' '})$($file.Path)"
            $fileTab.Add($key,$file)

            $folderKey = "$($folder.FolderPath.TrimEnd('/'))"
            if($fileTab.ContainsKey($folderKey)){
              $fileTab.Remove($folderKey)
            }
          }
        }
  
# Get VM inventory
        Get-VM -Datastore $ds | %{
          $_.ExtensionData.LayoutEx.File | %{
            if($fileTab.ContainsKey($_.Name)){
              $fileTab.Remove($_.Name)
            }
          }
        }
  
# Get Template inventory
        Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{
          $_.ExtensionData.LayoutEx.File | %{
            if($fileTab.ContainsKey($_.Name)){
              $fileTab.Remove($_.Name)
            }
          }
        }

# Remove system files &amp; folders from list
        $systemFiles = $fileTab.Keys | where{$_ -match "] \.|vmkdump"}
        $systemFiles | %{
          $fileTab.Remove($_)
        }

# Organise remaining files
        if($fileTab.Count){
          $fileTab.GetEnumerator() | %{
            $obj = [ordered]@{
              Name = $_.Value.Path
              Folder = $_.Name
              Size = $_.Value.FileSize
              CapacityKB = $_.Value.CapacityKb
              Modification = $_.Value.Modification
              Owner = $_.Value.Owner
              Thin = $_.Value.Thin
              Extents = $_.Value.DiskExtents -join ','
              DiskType = $_.Value.DiskType
              HWVersion = $_.Value.HardwareVersion
            }
            New-Object PSObject -Property $obj
          }
          Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tFound orphaned files on $($ds.Name)!"
        }
        else{
          Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tNo orphaned files found on $($ds.Name)."
        }
      }
    }
  }
}</pre><p></p>
<h3>Annotations</h3>
<p><strong>Line 28-57</strong>: The script constructs the <a href="https://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreBrowser.html#searchSubFolders" target="_blank" rel="noopener noreferrer">SearchDatastoreSubFolders</a> parameter in the Begin block. This parameter will be the same for all datastores.</p>
<p><strong>Line 56</strong>: To get maximum detail for the returned files, the script uses all available FileQuery variations</p>
<p><strong>Line 62-64</strong>: Cheap <a href="https://www.vmware.com/support/developer/PowerCLI/PowerCLI60R3/html/about_obn.html" target="_blank" rel="noopener noreferrer">OBN</a> implementation</p>
<p><strong>Line 67</strong>: The script only looks at <strong>shared</strong> <strong>VMFS</strong> datastores</p>
<p><strong>Line 71</strong>: This hash table will be used to determine which file/folder is orphaned or not. First all the files the method fins are placed in the hash table. Then the files that belong to VMs and Templates are removed. Finally some system files are removed. What is left are orphaned files.</p>
<p><strong>Line 76</strong>: Get all the files on the datastore with the <a href="https://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreBrowser.html#searchSubFolders" target="_blank" rel="noopener noreferrer">SearchDatastoreSubFolders</a> method</p>
<p><strong>Line 77-87</strong>: Enter the files in the hash table</p>
<p><strong>Line 83-85</strong>: Take care of the folder entries. If a file inside a folder is encountered, the script also removes the folder itself from the hash table</p>
<p><strong>Line 90-96</strong>: Remove all files that belong to registered VMs from the hash table</p>
<p><strong>Line 99-105</strong>: Remove all files that belong to registered Templates from the hash table</p>
<p><strong>Line 108-111</strong>: Remove system files. For now these all files that are located in folders that start with a dot, or in a folder named vmkdump.</p>
<p><strong>Line 114-128</strong>: If there are entries left in the hash table, collect more information and create an ordered object containing that information.</p>
<h2>Sample Usage</h2>
<p>The use of this function is rather straightforward, call the function with a datastorename or a datastore object.</p><pre class="urvanov-syntax-highlighter-plain-tag">Get-VmwOrphan -Datastore MyDS1</pre><p>or</p><pre class="urvanov-syntax-highlighter-plain-tag">$ds = Get-Datastore -Name MyDS1

Get-VmwOrphan -Datastore $ds</pre><p>The function also accepts the datastore objects via the pipeline. You can do</p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Cluster -Name MyCluster | Get-Datastore | Get-VmwOrphan</pre><p>The objects that are returned by the function, depending on the type of file, contain information about the file. The following sample output shows how some properties are specific to certain file types.</p>
<p><a href="https://www.lucd.info/2016/09/13/orphaned-files-revisited/orphan-1/" rel="attachment wp-att-5392"><img decoding="async" class="alignnone wp-image-5392 size-medium" src="https://lucd.info/wp-content/uploads/2016/09/orphan-1-262x300.jpg" alt="orphan-1" width="262" height="300" srcset="https://www.lucd.info/wp-content/uploads/2016/09/orphan-1-262x300.jpg 262w, https://www.lucd.info/wp-content/uploads/2016/09/orphan-1.jpg 505w" sizes="(max-width: 262px) 100vw, 262px" /></a></p>
<p>If you want to create an orphaned files report for multiple datastores, it is handy to capture the results for each datastore in a separate worksheet in an Excel spreadsheet.</p>
<p>The following sample code uses <a href="https://twitter.com/dfinke" target="_blank" rel="noopener noreferrer">Doug Finke</a>&#8216;s <a href="https://github.com/dfinke/ImportExcel" target="_blank" rel="noopener noreferrer">ImportExcel</a> module to accomplish that.</p><pre class="urvanov-syntax-highlighter-plain-tag">$reportName = 'C:\orphan-report.xlsx'

foreach($ds in (Get-Cluster -Name MyCluster | Get-Datastore | Get-VmwOrphan | Group-Object -Property {$_.Folder.Split(']')[0].TrimStart('[')})){
    $ds.Group | Export-Excel -Path $reportName -WorkSheetname $ds.Name -AutoSize -AutoFilter -FreezeTopRow
}</pre><p>The resulting spreadsheet has all the orphaned files, with a separate worksheet for each datastore that has orphaned files.</p>
<p><a href="https://www.lucd.info/2016/09/13/orphaned-files-revisited/orphan-2/" rel="attachment wp-att-5397"><img decoding="async" class="alignnone wp-image-5397 size-medium" src="https://lucd.info/wp-content/uploads/2016/09/orphan-2-300x79.jpg" alt="orphan-2" width="300" height="79" srcset="https://www.lucd.info/wp-content/uploads/2016/09/orphan-2-300x79.jpg 300w, https://www.lucd.info/wp-content/uploads/2016/09/orphan-2-768x203.jpg 768w, https://www.lucd.info/wp-content/uploads/2016/09/orphan-2-1024x271.jpg 1024w, https://www.lucd.info/wp-content/uploads/2016/09/orphan-2.jpg 1124w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Enjoy!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2016/09/13/orphaned-files-revisited/feed/</wfw:commentRss>
			<slash:comments>92</slash:comments>
		
		
			</item>
		<item>
		<title>VMFS Datastores &#8211; Expand and Extend</title>
		<link>https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/</link>
					<comments>https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Fri, 29 Jul 2016 13:30:52 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[expand]]></category>
		<category><![CDATA[extend]]></category>
		<category><![CDATA[LUN]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Expand]]></category>
		<category><![CDATA[Extend]]></category>
		<category><![CDATA[Increase]]></category>
		<category><![CDATA[VMFS]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=5347</guid>

					<description><![CDATA[We all know, and love, PowerCLI&#8216;s New-Datastore and Set-Datastore cmdlets to create and [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>We all know, and love, <a href="https://communities.vmware.com/community/vmtn/automationtools/powercli" target="_blank">PowerCLI</a>&#8216;s <a href="https://www.vmware.com/support/developer/PowerCLI/PowerCLI63R1/html/New-Datastore.html" target="_blank">New-Datastore</a> and <a href="https://www.vmware.com/support/developer/PowerCLI/PowerCLI63R1/html/Set-Datastore.html" target="_blank">Set-Datastore</a> cmdlets to create and manipulate <strong>VMFS datastores</strong>. But when we look at the functionality available through the Web Client, there is one interesting feature for manipulating VMFS datastores that is missing from the <a href="https://communities.vmware.com/community/vmtn/automationtools/powercli" target="_blank">PowerCLI</a> cmdlets. The <strong>Increase</strong> button, which allows us to <strong>Expand</strong> or <strong>Extend</strong> an existing VMFS datastore<sup>*</sup>.</p>
<p style="padding-left: 30px;"><a href="https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/ds-increase/" rel="attachment wp-att-5348"><img loading="lazy" decoding="async" class="alignnone wp-image-5348 size-medium" src="https://lucd.info/wp-content/uploads/2016/07/DS-Increase-300x148.jpg" alt="DS-Increase" width="300" height="148" srcset="https://www.lucd.info/wp-content/uploads/2016/07/DS-Increase-300x148.jpg 300w, https://www.lucd.info/wp-content/uploads/2016/07/DS-Increase-768x378.jpg 768w, https://www.lucd.info/wp-content/uploads/2016/07/DS-Increase.jpg 840w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>Recently there were a couple of threads on this subject in the <a href="https://communities.vmware.com/community/vmtn/automationtools/powercli/content?filterID=contentstatus[published]~objecttype~objecttype[thread]" target="_blank">VMTN PowerCLI Community</a>, so I decided to streamline my quick-and-dirty scripts into something more presentable, and create a <strong>PowerShell module</strong> to bundle the functions. I present the <strong>VMFSIncrease</strong> module!<br />
The VMFSIncrease module will also be my first contribution to the <a href="https://github.com/vmware/PowerCLI-Example-Scripts" target="_blank">PowerCLI Community Repository</a>! More on that further on in this post.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>* <sub>The expand and extend functions for a VMFS datastore depend on the availability of free space on the VMFS datastore extents and/or the availability of free LUNs</sub></p>
<p><span id="more-5347"></span></p>
<h2>The Increase button</h2>
<p>The Increase button in fact offers two different methods to increase the size of a datastore. The definitions of two methods according to the</p>
<ul>
<li><strong>Expand</strong>: increases the capacity of an existing VMFS datastore by expanding (increasing the size of) an <strong>existing extent</strong> of the datastore</li>
<li><strong>Extend</strong>: Increases the capacity of an existing VMFS datastore by adding <strong>new extents</strong> to the datastore</li>
</ul>
<p>Perhaps the following schematic makes it a bit more clear.</p>
<p style="padding-left: 30px;"><a href="https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/vmfs-2/" rel="attachment wp-att-5358"><img loading="lazy" decoding="async" class="alignnone wp-image-5358 size-medium" src="https://lucd.info/wp-content/uploads/2016/07/vmfs-2-300x104.png" alt="vmfs-2" width="300" height="104" srcset="https://www.lucd.info/wp-content/uploads/2016/07/vmfs-2-300x104.png 300w, https://www.lucd.info/wp-content/uploads/2016/07/vmfs-2.png 679w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>The schematic shows a VMFS datastore with one extent, on LUN A. If we want to increase the Used capacity, we can do an Expand, on the same extent (LUN A). Or we can do an Extend on a new LUN, in this case LUN B.In the case of the Extend, the VMFS datastore will now have two extents, LUN A and LUN B.</p>
<p>Note that for the Expand and the Extent you do not need to use all of the free space. The following is perfectly possible.</p>
<p style="padding-left: 30px;"><a href="https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/vmfs-1/" rel="attachment wp-att-5356"><img loading="lazy" decoding="async" class="alignnone wp-image-5356 size-medium" src="https://lucd.info/wp-content/uploads/2016/07/vmfs-1-300x109.png" alt="vmfs-1" width="300" height="109" srcset="https://www.lucd.info/wp-content/uploads/2016/07/vmfs-1-300x109.png 300w, https://www.lucd.info/wp-content/uploads/2016/07/vmfs-1.png 690w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>The Increase button presents the user with a series of candidate LUNs. The Expand and Extend candidate LUNs are intermixed in that list. The underlying API method makes sure that the LUNs are not already used by another <strong>datastore</strong> or by a <strong>RDM</strong> disk.</p>
<h2>The Module</h2>
<p>The module is available in my GitHub <a href="https://github.com/lucdekens/VMFSIncrease" target="_blank">VMFSIncrease</a> repository.</p>
<h2>Sample runs</h2>
<h3>Reporting</h3>
<p>The Get-VmfsDatastoreInfo displays basic information about the extents and the partitions that make up the datastore.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-VmfsDatastoreInfo -Datastore TestDS</pre><p></p>
<p>This produces something like this</p>
<p style="padding-left: 30px;"><a href="https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/vmfs-3/" rel="attachment wp-att-5362"><img loading="lazy" decoding="async" class="alignnone wp-image-5362 size-medium" src="https://lucd.info/wp-content/uploads/2016/07/vmfs-3-217x300.png" alt="vmfs-3" width="217" height="300" srcset="https://www.lucd.info/wp-content/uploads/2016/07/vmfs-3-217x300.png 217w, https://www.lucd.info/wp-content/uploads/2016/07/vmfs-3.png 478w" sizes="auto, (max-width: 217px) 100vw, 217px" /></a></p>
<p>The Datastore lives on one extent, and on that extent there are three partitions. The partition marked with (2) is the part where the VMFS Datastore lives. Part (3) is the free space, and part (1) is for alignment.</p>
<p>To check how we can increase the capacity of the Datastore, we can run</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-VmfsDatastoreIncrease -Datastore TestDS</pre><p></p>
<p>This returns something like this</p>
<p><a href="https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/vmfs-4/" rel="attachment wp-att-5363"><img loading="lazy" decoding="async" class="alignnone wp-image-5363 size-medium" src="https://lucd.info/wp-content/uploads/2016/07/vmfs-4-300x166.png" alt="vmfs-4" width="300" height="166" srcset="https://www.lucd.info/wp-content/uploads/2016/07/vmfs-4-300x166.png 300w, https://www.lucd.info/wp-content/uploads/2016/07/vmfs-4.png 446w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>The returned information shows that there are two options to increase the capacity of the Datastore. In (1) we see that we can Expand the extent by 80GB. In (2) we see that we can Extend the capacity by 100GB by adding a new extent to the Datastore.</p>
<h3>Expand</h3>
<p>The Help page for the New-VmfsDatastoreIncrease function already contains several examples on how to use the function. But to give you an idea what is possible, just a few examples.</p>
<p>We have the possibility to add up to 80GB. If we don&#8217;t specify a size, all the free space on the extent is used.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VmfsDatastoreIncrease -Datastore 'TestDS' -Expand</pre><p></p>
<p>If we do specify how much we want to increase the capacity, only that specific amount of space from the free space will be taken.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VmfsDatastoreIncrease -Datastore 'TestDS' -Expand -IncreaseSizeGB 25</pre><p></p>
<p>If we have a Datastore that spans more than one extent, we can, through the Canonicalname parameter, indicate on which extent the increase shall be taken.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VmfsDatastoreIncrease -Datastore 'TestDS' -Expand -IncreaseSizeGB 15 -CanonicalName 'naa.60050123017775af1800000000000011'</pre><p></p>
<h3>Extend</h3>
<p>As we explained in the beginning of the post, with the Extend switch we indicate that we want to increase the capacity on a new extent. Again we can take the full extent.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VmfsDatastoreIncrease -Datastore 'TestDS' -Extend -CanonicalName 'naa.60050123017775af1800000000000012'</pre><p></p>
<p>Interesting to note, if you don&#8217;t specify a LUN, through the Canonicalname parameter, the function will order the available LUNs alphanumerically on their Canonicalname, and take the first one. So the following is perfectly possible, provided of course there are free LUNs available.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VmfsDatastoreIncrease -Datastore 'TestDS' -Extend</pre><p></p>
<p>And, as with the Expand option, you do not need to use all of the available space with the Extend option. You can control how much space is taken through the IncreaseSizeGB parameter.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VmfsDatastoreIncrease -Datastore 'TestDS' -Extend -IncreaseSizeGB 50 -CanonicalName 'naa.60050123017775af1800000000000012'</pre><p></p>
<p>The option is also available without specifying a LUN. The function uses the same logic as was mentioned before, it will order the available LUNs alphanumerically on their Canonicalname, and take the first one.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VmfsDatastoreIncrease -Datastore 'TestDS' -Extend -IncreaseSizeGB 35</pre><p></p>
<h2>PowerCLI Community Repository</h2>
<p>Since a couple of days the long awaited <a href="https://github.com/vmware/PowerCLI-Example-Scripts" target="_blank">PowerCLI Community Repository</a> is live! More info can be found in the <a href="https://blogs.vmware.com/PowerCLI/2016/07/updating-vmware-powercli-community-repository.html" target="_blank">Updating the VMware PowerCLI Community Repository!</a> post over on the PowerCLI Blog.</p>
<p>If you have any scripts, functions, modules&#8230; that might be useful for the community, please submit them there.</p>
<p>The VMFSIncrease module will be available on the <a href="https://github.com/vmware/PowerCLI-Example-Scripts" target="_blank">PowerCLI Community Repository</a> shortly.</p>
<p>&nbsp;</p>
<p>Enjoy, and share!</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>Remove old VM monitor dump files</title>
		<link>https://www.lucd.info/2013/04/01/remove-old-vm-monitor-dump-files/</link>
					<comments>https://www.lucd.info/2013/04/01/remove-old-vm-monitor-dump-files/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Mon, 01 Apr 2013 20:20:15 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[dump]]></category>
		<category><![CDATA[Folder]]></category>
		<category><![CDATA[remove]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=4427</guid>

					<description><![CDATA[When you need to move the content of one or more datastores, you [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>When you need to move the content of one or more datastores, you sometimes stumble upon files that you didn&#8217;t know where there. One such type of files are dump files that are stored in a VM&#8217;s directory on the datastore.</p>
<p>The files I encountered were named like this:</p>
<ul>
<li>vmware64-core*.gz</li>
<li>vmware-vmx-zdump.*</li>
</ul>
<p>There isn&#8217;t a lot of information available on what exactly these files are used for, besides that they seem to be created when the VM Monitor encounters a crash or a serious problem.</p>
<p>Since these files were quite old, and since I didn&#8217;t have any open tickets with VMware, I decided to remove these files. But of course in the PowerCLI way with a function <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><span id="more-4427"></span></p>
<h2>The Script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-Dump {
&lt;#  
.SYNOPSIS  Finds dump files on datastores   
.DESCRIPTION The function will look for dump files on
  one or more datastores. The dump filenames contain &quot;zdump&quot;
  or &quot;core&quot;
.NOTES  Author:  Luc Dekens  
.PARAMETER Datastore
  The datastore(s) the function has to search.
.EXAMPLE
  PS&gt; Get-Dump -Datastore DS1
.EXAMPLE
  PS&gt; Get-Datastore -Name DS* | Get-Dump
#&gt;

  param(
    [Parameter(ValueFromPipeline=$true)]
    [PSObject[]]$Datastore
  )
  
  begin {
    $spec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
    $spec.MatchPattern = &quot;*zdump*&quot;,&quot;*core*&quot;
    $spec.details = New-Object VMware.Vim.FileQueryFlags
    $spec.details.fileType = $true
    $spec.details.fileSize = $true
    $spec.details.modification = $true
    $spec.details.fileOwner = $true
    $spec.sortFoldersFirst = $true
  }
  process {
    if(!$Datastore){
      $Datastore = Get-Datastore
    }
    else{
      $Datastore | %{
        $Datastore = if($_ -is [System.String]){
          Get-Datastore -Name $_
        }
        else {$_}
      }
    }
    $Datastore | %{
      $dsBrowser = Get-View $_.ExtensionData.Browser
      $task = $dsBrowser.SearchDatastoreSubFolders(&quot;[&quot; + $_.Name + &quot;] &quot;,$spec)
      $task | Where {$_.File} | Select -Property FolderPath -ExpandProperty File |
        where {$_ -isnot &quot;VMware.Vim.FolderFileInfo&quot;} |
        Select Path,Modification,FileSize,FolderPath
    }
  }
}

function Remove-Dump {
&lt;#  
.SYNOPSIS  Removes files on datastores   
.DESCRIPTION The function removes files on datastores. The
  filenames need to be provided as objects returned by the
  Get-Dump function.
.NOTES  Author:  Luc Dekens  
.PARAMETER File
  The file(s) to remove
.EXAMPLE
  PS&gt; Get-Dump -Datastore DS1 | Remove-Dump
.EXAMPLE
  PS&gt; Get-Datastore -Name DS* | Remove-Dump -Confirm:$false 
#&gt;

  [cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='High')]
  param(
    [Parameter(ValueFromPipeline=$true)]
    [PSObject[]]$File
  )

  begin {
    $fileMgr = Get-View FileManager
  }
  
  process {
    $File | %{
      $dsName = $_.FolderPath.Split(' ')[0].TrimStart('[').TrimEnd(']')
      $dc = (Get-Datastore -Name $dsName).Datacenter.ExtensionData.MoRef
      $name = $_.FolderPath + $_.Path
      if($pscmdlet.ShouldProcess($dsName,&quot;Deleting file $name&quot;)){
        $fileMgr.DeleteDatastoreFile($name,$dc)
      }
    }
  }
}</pre><p></p>
<h4>Annotations</h4>
<p><strong>Line 18</strong>: The function accepts one or more datastores. The datastores can be passed as datastore objects that are returned by the <a href="https://www.vmware.com/support/developer/PowerCLI/PowerCLI51R2/html/Get-Datastore.html" target="_blank">Get-Datastore</a> cmdlet, or they can be passed as datastorenames.</p>
<p><strong>Line 22-29</strong>: The <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreBrowser.SearchSpec.html" target="_blank">HostDatastoreBrowserSearchSpec</a> that is used to find the dump files. In the MatchPattern property the function defines the name patterns that should be looked for. Since this specification always is the same, we define it in the Begin section of the function.</p>
<p><strong>Line 32-42</strong>: The function accepts datastore objects or datastore names, these lines take care of converting datastore names to datastore objects. If no Datastore value was passed, the function will search all the datastores.</p>
<p><strong>Line 45</strong>: The function uses the <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreBrowser.html#searchSubFolders" target="_blank">SearchDatastoreSubFolders</a> to find the dump files. The same logic could also be done through the PowerCLI datastore provider. But my tests showed that the <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreBrowser.html#searchSubFolders" target="_blank">SearchDatastoreSubFolders</a> method is <strong><span style="background-color: #ffff00;">20 times faster</span></strong> !</p>
<p><strong>Line 48</strong>: The function returns object that have the basic information about the file; the name, the path, the modification time and the size.</p>
<p><strong>Line 68</strong>: The Remove-Dump function supports the WhatIf and Confirm parameters.</p>
<p><strong>Line 75</strong>: The <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.FileManager.html" target="_blank">FileManager</a> is preferred over the <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreBrowser.html#searchSubFolders" target="_blank">HostDatastoreBrowser</a> to remove files.</p>
<p><strong>Line 80-81</strong>: Since the function provides the filepath as &#8220;<em>[datastore] folder/file</em>&#8220;, it has to pass the datacenter MoRef to the <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.FileManager.html#deleteFile" target="_blank">DeleteDatastoreFile</a> method.</p>
<p><strong>Line 83</strong>: This handles the use of the <strong>WhatIf</strong> parameter.</p>
<h2>Sample Usage</h2>
<p>The functions are very simple to use. To look for dump files on a specific datastore, you can do</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">$DS = Get-Datastore -Name ds1
Get-Dump -Datastore $DS</pre><p></p>
<p>This will, provided there are dump files present on that datastore, return an object for each dump file. The output on the console looks something like this.</p>
<p><a href="https://www.lucd.info/2013/04/01/remove-old-vm-monitor-dump-files/dump-files/" rel="attachment wp-att-4428"><img loading="lazy" decoding="async" class="alignnone  wp-image-4428" alt="dump-files" src="https://lucd.info/wp-content/uploads/2013/04/dump-files.png" width="596" height="84" srcset="https://www.lucd.info/wp-content/uploads/2013/04/dump-files.png 851w, https://www.lucd.info/wp-content/uploads/2013/04/dump-files-300x42.png 300w" sizes="auto, (max-width: 596px) 100vw, 596px" /></a></p>
<p>The remove the dump files you can just place the returned objects on the pipeline and call the Remove-Dump function.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Datastore -Name ds* | Get-Dump | Remove-Dump -Confirm:$false</pre><p></p>
<p>You can of course remove files a bit more intelligently. You could for example remove all dump files that are more than 1 year old.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Dump | Where {$_.Modification -lt $date} | Remove-Dump -Confirm:$false</pre><p></p>
<p>Note that the Modifcation property holds the UTC time.</p>
<p>Enjoy !</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2013/04/01/remove-old-vm-monitor-dump-files/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Find free SCSI LUNs</title>
		<link>https://www.lucd.info/2013/01/15/find-free-scsi-luns/</link>
					<comments>https://www.lucd.info/2013/01/15/find-free-scsi-luns/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Tue, 15 Jan 2013 21:42:41 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[LUN]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=4311</guid>

					<description><![CDATA[Another post that comes from a VMTN PowerCLI Community question. Jeff wanted to [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Another post that comes from a <a href="https://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=discussions&amp;start=0" target="_blank">VMTN PowerCLI Community</a> question. <strong>Jeff</strong> wanted to find the free SCSI LUNs in his environment.<br />
While answering that <a href="https://communities.vmware.com/thread/432110?tstart=0" target="_blank">thread</a> I was amazed there was no PowerCLI function written yet to provide this functionality. At least that was what my friend Google told me <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Since there exists a SDK method that makes retrieving free SCSI LUNs quite easy, the function I came up with isn&#8217;t too complex.</p>
<p>But it should help you in further <strong>automating</strong> the setup of your datastores.</p>
<p><span id="more-4311"></span></p>
<h2>The Script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-FreeScsiLun {

&lt;#  
.SYNOPSIS  Find free SCSI LUNs  
.DESCRIPTION The function will find the free SCSI LUNs
  on an ESXi server
.NOTES  Author:  Luc Dekens  
.PARAMETER VMHost
    The VMHost where to look for the free SCSI LUNs  
.EXAMPLE
   PS&gt; Get-FreeScsiLun -VMHost $esx
.EXAMPLE
   PS&gt; Get-VMHost | Get-FreeScsiLun
#&gt;

  param (
  [parameter(ValueFromPipeline = $true,Position=1)]
  [ValidateNotNullOrEmpty()]
  [VMware.VimAutomation.Client20.VMHostImpl]
  $VMHost
  )

  process{
    $storMgr = Get-View $VMHost.ExtensionData.ConfigManager.DatastoreSystem

    $storMgr.QueryAvailableDisksForVmfs($null) | %{
      New-Object PSObject -Property @{
        VMHost = $VMHost.Name
        CanonicalName = $_.CanonicalName
        Uuid = $_.Uuid
        CapacityGB = [Math]::Round($_.Capacity.Block * $_.Capacity.BlockSize / 1GB,2)
      }
    }
  }
}</pre><p></p>
<h4>Annotations</h4>
<p><strong>Line 24</strong>: The <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreSystem.html" target="_blank">HostDatastoreSystem</a> provides access to the method we are using</p>
<p><strong>Line 26</strong>: The <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.host.DatastoreSystem.html#queryAvailableDisksForVmfs" target="_blank">QueryAvailableDisksForVmfs</a> method is called with a $null argument. That way we tell the method that we do not want to extend an existing datastore, but that we want to retrieve all free LUNs that can be used to create a datastore.</p>
<p><strong>Line 27-32</strong>: The result is returned as an array of <a href="https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/vim.host.ScsiDisk.html" target="_blank">HostScsiDisk</a> objects. With the New-Object cmdlet we pass the information that you can eventually use in the <a href="https://www.vmware.com/support/developer/PowerCLI/PowerCLI51/html/New-Datastore.html" target="_blank">New-Datastore</a> cmdlet.</p>
<h2>Sample Usage</h2>
<p>The use of this function is quite simple as the following example will show</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">$esx = Get-VMHost -Name MyEsx

Get-FreeScsiLun -VMHost $esx | Format-List</pre><p></p>
<p>The result looks something like this. You can use the <strong>CanonicalName</strong> property in the <strong>Path</strong> parameter of the <a href="https://www.vmware.com/support/developer/PowerCLI/PowerCLI51/html/New-Datastore.html" target="_blank">New-Datastore</a> cmdlet.</p>
<p><a href="https://www.lucd.info/2013/01/15/find-free-scsi-luns/freelun1/" rel="attachment wp-att-4313"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4313" alt="freelun1" src="https://lucd.info/wp-content/uploads/2013/01/freelun1.png" width="607" height="143" srcset="https://www.lucd.info/wp-content/uploads/2013/01/freelun1.png 607w, https://www.lucd.info/wp-content/uploads/2013/01/freelun1-300x70.png 300w" sizes="auto, (max-width: 607px) 100vw, 607px" /></a></p>
<p>You can also use the function in a pipeline construct. For example something like this</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Cluster -Name MyCluster |
Get-VMHost |
Get-FreeScsiLun | Format-List</pre><p></p>
<p>On my test cluster with 2 nodes this will return the following results. And as we can see the free SCSI LUNs are visible on both nodes.</p>
<p><a href="https://www.lucd.info/2013/01/15/find-free-scsi-luns/freelun2/" rel="attachment wp-att-4314"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4314" alt="freelun2" src="https://lucd.info/wp-content/uploads/2013/01/freelun2.png" width="594" height="260" srcset="https://www.lucd.info/wp-content/uploads/2013/01/freelun2.png 594w, https://www.lucd.info/wp-content/uploads/2013/01/freelun2-300x131.png 300w" sizes="auto, (max-width: 594px) 100vw, 594px" /></a></p>
<p>Enjoy !</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2013/01/15/find-free-scsi-luns/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Monitor the size of your vDisks</title>
		<link>https://www.lucd.info/2012/12/02/monitor-the-size-of-your-vdisks/</link>
					<comments>https://www.lucd.info/2012/12/02/monitor-the-size-of-your-vdisks/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Sun, 02 Dec 2012 21:31:48 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[Thin Provisioning]]></category>
		<category><![CDATA[VMDK]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=4232</guid>

					<description><![CDATA[In a recent thread on the VMTN PowerCLI Community someone asked if it [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In a recent <a href="https://communities.vmware.com/message/2154603#2154603" target="_blank">thread</a> on the <a href="https://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=discussions" target="_blank">VMTN PowerCLI Community</a> someone asked if it is possible to get <strong>historical hard disk statistics</strong>. I referred the user to my <a href="https://www.lucd.info/2011/06/19/datastore-usage-statistics/" target="_blank">Datastore usage statistics</a> post, where I showed how to use the &#8220;<em>disk</em>&#8221; metrics to get that information.</p>
<p>But getting the individual vDisk statistics is a bit more tricky compared to getting the datastore statistics, as I showed in that post. The &#8220;<em>disk</em>&#8221; metrics hold the information, but the <strong>Instance</strong> that points to the <strong>MoRef value</strong> of a VM makes it a bit more tricky to retrieve.</p>
<p>Be <span style="background-color: #ffff00;">forewarned</span>, the &#8220;<em>disk</em>&#8221; metrics hold usage data for <strong>all</strong> the vDisks that a specific VM has on a <strong>specific datastore</strong>. You will <strong>not</strong> be able to get <strong>individual</strong> vDisk statistics, unless the vDisks are stored on different datastores !</p>
<p>On the positive side, the &#8220;<em>disk</em>&#8221; metrics will allow you to see how your vDisks increase in size over time. For your Thick vDisks that increase will be by <strong>expanding</strong> them, and for your Thin vDisks it will also show the natural <strong>growth</strong>.</p>
<p><span id="more-4232"></span></p>
<h2>The Script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">$datastoreName = &quot;MyDS&quot;
$targetVM = &quot;VM1&quot;,&quot;VM2&quot;,&quot;VM3&quot;
$monthsBack = 3
$interval = &quot;HI4&quot;

$ds = (Get-Datastore -Name $datastoreName).ExtensionData
$metric = &quot;disk.used.latest&quot;
$start = (Get-Date).AddMonths(-$monthsBack)

$vmTab = @{}

$localCulture = Get-Culture

Get-VM -Name $targetVM | %{
  $vmTab.Add($_.Id.Split('-')[2],$_.Name)
}

&amp;{Get-Stat2 -entity $ds -interval $interval -stat $metric -QueryInstances |
  where {$_.Instance -match &quot;^\d+$&quot; -and $vmTab.ContainsKey($_.Instance)} | %{
    Get-Stat2 -entity $ds -Instance $_.Instance -stat $metric -interval $interval -Start $start |
    Select @{N=&quot;VM&quot;;E={$vmTab[$_.Instance]}},Timestamp,Entity,Value,Unit,Interval
  }
} |
Group-Object -Property Timestamp | ForEach-Object -Process {
  $newObj = New-Object PSObject -Property @{
    Timestamp = [datetime]::Parse($_.Name,$localCulture)
  }
  $_.Group | %{
    Add-Member -InputObject $newObj -Name $_.VM -Value ($_.Value/1MB) -MemberType NoteProperty
  }
  $newObj
} |
Sort-Object -Property Timestamp |
Export-Csv &quot;C:\vdisk.csv&quot; -NoTypeInformation -UseCulture</pre><p></p>
<h4>Annotations</h4>
<p><strong>Line 1</strong>: The datastore for which the script will produce a report</p>
<p><strong> Line 2</strong>: The script looks for specific VMs on the datastore</p>
<p><strong>Line 4</strong>: The <strong>Historical Interval 4</strong> holds 1 entry per day, which is sufficient for monitoring vDisk growth. If you need finer samples change it to another Historical Interval, but note that the &#8220;<em>disk</em>&#8221; metrics are only available for the historical intervals.</p>
<p><strong>Line 12</strong>: This will allow the script to interpret dates correctly, in other words it allows the script later on to read dates in the format &#8220;mm/dd/yyyy&#8221; and in the &#8220;dd/mm/yyyy&#8221; format.</p>
<p><strong>Line 14-16</strong>: For the VMs we want to report upon, the script fetches the <strong>Value</strong> property of its <strong>MoRef</strong>. This Value corresponds with the Instance that will be returned with the performance data, and that allows the script to link the Instance to the VM name.</p>
<p><strong>Line 18-19</strong>: With the <strong>QueryInstances</strong> parameter the script requests all the available <strong>Instances</strong>, in other words VM specific performance data. The script checks if the <strong>Instance</strong> is in the <strong>MoRef.Value</strong> format and if the Instance corresponds with one of the VMs we want to report upon.</p>
<p><strong>Line 20-21</strong>: For all the qualifying <strong>Instances</strong> the script fetches the performance data.</p>
<p><strong>Line 24-32</strong>: The performance data is grouped on the <strong>Timestamp</strong>. All the individual performance objects with a specific Timestamp, each for 1 Instance (or 1 VM), are combined into 1 object with a <strong>property</strong> for each Instance.</p>
<p><strong>Line 26</strong>: The <strong>Timestamp</strong> became a string, in a format defined by the <strong>locale</strong>, in the <strong>Group-Object</strong> earlier on. To interpret the date string correctly the script calls the <strong>Parse</strong> method and passes the locale object.</p>
<h2>Sample Usage</h2>
<p>The script uses my <strong>Get-Stat2</strong> function I have used before. Make sure that function is known before calling the script above. The latest version of my <strong>Get-Stat2</strong> function can be downloaded below.</p>
<p>[wpfilebase tag=file id=11]</p>
<p>The CSV file that is produced by the script looks like this:</p>
<p><img loading="lazy" decoding="async" class="wp-image-4234 alignnone" title="vdisk-stats-1" src="https://lucd.info/wp-content/uploads/2012/12/vdisk-stats-1.png" alt="" width="657" height="279" srcset="https://www.lucd.info/wp-content/uploads/2012/12/vdisk-stats-1.png 730w, https://www.lucd.info/wp-content/uploads/2012/12/vdisk-stats-1-300x127.png 300w" sizes="auto, (max-width: 657px) 100vw, 657px" /></p>
<p>If you have a PowerShell module or snapin that allows you to produce graphs, you can make the result a bit fancier.</p>
<p>I replaced the <strong>Export-Csv</strong> line with the <strong>Out-Chart</strong> cmdlet from <a href="https://www.softwarefx.com/sfxSqlProducts/powerGadgets/default.aspx" target="_blank">PowerGadgets</a>.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Out-Chart -Gallery Lines `
  -AllSeries_MarkerSize 0 `
  -Title &quot;vDisk monitoring&quot; `
  -AxisX_Title_Text &quot;Date&quot; `
  -AxisY_Title_Text &quot;Space (GB)&quot; `
  -Values $targetVM `
  -Label {([datetime]::Parse($_.Timestamp,$localCulture)).ToString(&quot;dd-MM&quot;)}</pre><p></p>
<p>Notice how I use the Parse method to interpret the dates correctly for the locale where the script runs.<br />
The resulting picture looks as follows.</p>
<p><img loading="lazy" decoding="async" class="alignnone  wp-image-4236" title="vdisk-stats-2" src="https://lucd.info/wp-content/uploads/2012/12/vdisk-stats-2.png" alt="" width="625" height="346" srcset="https://www.lucd.info/wp-content/uploads/2012/12/vdisk-stats-2.png 781w, https://www.lucd.info/wp-content/uploads/2012/12/vdisk-stats-2-300x165.png 300w" sizes="auto, (max-width: 625px) 100vw, 625px" /></p>
<p>This vDisk reporting script can be expanded in many ways. We could for example find all created and removed VMs, which would give us a complete report of which VMs have hsitorically been using your datastore space. But that will be for a later post.</p>
<p>Enjoy !</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2012/12/02/monitor-the-size-of-your-vdisks/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Test if the datastore can be unmounted</title>
		<link>https://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/</link>
					<comments>https://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Sun, 15 Apr 2012 21:29:48 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SDRS]]></category>
		<category><![CDATA[SIOC]]></category>
		<category><![CDATA[unmount]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=3980</guid>

					<description><![CDATA[Lately I have been playing around with the new Storage related features in [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Lately I have been playing around with the new Storage related features in vSphere 5. One of the novelties is that you can now <strong>unmount</strong> a VMFS datastore and <strong>detach</strong> a SCSI LUN through the API.<br />
To be able to unmount a datastore, some <strong>conditions</strong> have to be met. In the vSphere Client you get an informative popup that tells what is prohibiting the datastore unmount. If not all conditions are met, you can not continue with the unmount.</p>
<p><a href="https://lucd.info/wp-content/uploads/2012/04/Datastore-unmount.png"><img loading="lazy" decoding="async" class=" wp-image-3906 alignnone" title="DS unmount" src="https://lucd.info/wp-content/uploads/2012/04/Datastore-unmount.png" alt="" width="421" height="316" /></a></p>
<p>Nice feature, but what for those of us that want to automate this ?</p>
<p><span style="background-color: #ffff00;"><strong>Update October 28th 2012</strong></span>: Take into account that the datastorecluster is not connected to a host that is part of a cluster. Skip the HA heartbeat test.</p>
<p><span style="background-color: #ffff00;"><strong>Update April 23th 2012</strong></span>: Use the <a href="https://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.ClusterComputeResource.html#retrieveDasAdvancedRuntimeInfo" target="_blank">RetrieveDasAdvancedRuntimeInfo</a> method to find the actual datastores that are used for the heartbeat.</p>
<p><span id="more-3980"></span></p>
<h2>What to look for ?</h2>
<p>From the popup, it is quite obvious what specific feature can prohibit the unmount of a datastore.</p>
<p>But if you look at Cormac&#8217;s post called <a href="https://blogs.vmware.com/vsphere/2012/02/what-could-be-writing-to-a-vmfs-when-no-virtual-machines-are-running.html" target="_blank">What could be writing to a VMFS when no Virtual Machines are running?</a>, there are a couple of other settings that might influence the ability to unmount a datastore.</p>
<p>In Cormac&#8217;s post you&#8217;ll find that a <strong>Distributed Virtual Switch configuration file</strong> or the presence of a <strong>scratch partition</strong> might also cause IO that would prevent a datastore unmount.</p>
<p>So I decided to expand the function with a check for those 2 additional causes.</p>
<h2>The script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-DatastoreUnmountStatus{
  &lt;#
.SYNOPSIS  Check if a datastore can be unmounted.
.DESCRIPTION The function checks a number of prerequisites
  that need to be met to be able to unmount a datastore.
.NOTES  Author:  Luc Dekens
.PARAMETER Datastore
  The datastore for which you want to chekc the conditions.
  You can pass the name of the datastore or the Datastore
  object returned by Get-Datastore
.EXAMPLE
  PS&gt; Get-DatastoreUnmountStatus -Datastore DS1
.EXAMPLE
  PS&gt; Get-Datastore | Get-DatastoreUnmountStatus
#&gt;
  param(
    [CmdletBinding()]
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [PSObject[]]$Datastore
  )

  process{
    foreach($ds in $Datastore){
      if($ds.GetType().Name -eq &quot;string&quot;){
        $ds = Get-Datastore -Name $ds
      }
      $parent = Get-View $ds.ExtensionData.Parent
      New-Object PSObject -Property @{
        Datastore = $ds.Name
        # No Virtual machines
        NoVM = $ds.ExtensionData.VM.Count -eq 0
        # Not in a Datastore Cluster
        NoDastoreClusterMember = $parent -isnot [VMware.Vim.StoragePod]
        # Not managed by sDRS
        NosDRS = &amp;{
          if($parent -is [VMware.Vim.StoragePod]){
            !$parent.PodStorageDrsEntry.StorageDrsConfig.PodConfig.Enabled
          }
          else {$true}
        }
        # SIOC disabled
        NoSIOC = !$ds.StorageIOControlEnabled
        # No HA heartbeat
        NoHAheartbeat = &amp;{
          $hbDatastores = @()
          $cls = Get-View -ViewType ClusterComputeResource -Property Host |
          where{$_.Host -contains $ds.ExtensionData.Host[0].Key}
          if($cls){
            $cls | %{
              (                $_.RetrieveDasAdvancedRuntimeInfo()).HeartbeatDatastoreInfo | %{
                $hbDatastores += $_.Datastore
              }
            }
            $hbDatastores -notcontains $ds.ExtensionData.MoRef
          }
          else{$true}
        }
        # No vdSW file
        NovdSwFile = &amp;{
          New-PSDrive -Location $ds -Name ds -PSProvider VimDatastore -Root '\' | Out-Null
          $result = Get-ChildItem -Path ds:\ -Recurse |
          where {$_.Name -match '.dvsData'}
          Remove-PSDrive -Name ds -Confirm:$false
          if($result){$false}else{$true}
        }
        # No scratch partition
        NoScratchPartition = &amp;{
          $result = $true
          $ds.ExtensionData.Host | %{Get-View $_.Key} | %{
            $diagSys = Get-View $_.ConfigManager.DiagnosticSystem
            $dsDisks = $ds.ExtensionData.Info.Vmfs.Extent | %{$_.DiskName}
            if($dsDisks -contains $diagSys.ActivePartition.Id.DiskName){
              $result = $false
            }
          }
          $result
        }
      }
    }
  }
}</pre><p></p>
<h4>Annotations</h4>
<p><strong>Line 24-26</strong>: A simple Object By Name implementation. It allows to pass the datastores by name or by object to the function.</p>
<p><strong>Line 27</strong>: The parent of the datastore is used in a couple of tests further on in the script</p>
<p><strong>Line 31</strong>: Test if there are any VMs or Templates present on the datastore</p>
<p><strong>Line 33</strong>: Test if the datastore belongs to a Storage Cluster</p>
<p><strong>Line 35-40</strong>: Test if the datastore is managed by Storage DRS. The Enabled property in the <a href="https://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.storageDrs.PodConfigInfo.html" target="_blank">StorageDrsPodConfigInfo</a> object is used as the indicator.</p>
<p><strong>Line 42</strong>: Test if SIOC is enabled for the datastore</p>
<p><strong>Line 44-57</strong>: Test if the datastore is one of the Heartbeat Datastores. The test first gets all the clusters known in vCenter and then filters out those clusters that have hosts on which the datastore is visible.</p>
<p><strong>Line 48,56</strong>: If the host is not part of a cluster, the HA heartbeat test is considered as successful.</p>
<p><strong>Line 59-65</strong>: Test to see if the is a Distributed Virtual Switch configuration file present on the datastore.</p>
<p><strong>Line 67-77</strong>: Test if the datastore is used as a scratch partition.</p>
<h2>Sample usage</h2>
<p>The function can be used in a stand-alone or in a pipeline construct.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-DatastoreUnmountStatus -Datastore DS1</pre><p></p>
<p>The pipeline construct could look like this</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Datastore DS* | Get-DatastoreUnmountStatus</pre><p></p>
<p>The function produces 1 object per datastore. Each of the properties in the object represents 1 test that the function executes. Something like this.</p>
<p><a href="https://lucd.info/wp-content/uploads/2012/04/dsUnmountout.png"><img loading="lazy" decoding="async" class=" wp-image-3906 alignnone" title="DS unmount output" src="https://lucd.info/wp-content/uploads/2012/04/dsUnmountout.png" alt="" width="576" height="130" /></a></p>
<p>The output shows us that we will probably not be able to unmount datastore DS1, because:</p>
<ul>
<li>the datastore is part of a Datastore Cluster</li>
<li>the datastore is managed by Storage DRS</li>
<li>there are VMs (or Templates) on the datastore</li>
<li>the datastore is used by the Datastore Heartbeat</li>
<li>the datastore has SIOC enabled</li>
</ul>
<p>The functions to solve this and allow an unmount of the datastore will follow in some future posts.</p>
<p>Enjoy !</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/feed/</wfw:commentRss>
			<slash:comments>20</slash:comments>
		
		
			</item>
		<item>
		<title>vSphere 5 Top 10 – VMFS5</title>
		<link>https://www.lucd.info/2011/12/19/vsphere-5-top-10-vmfs5/</link>
					<comments>https://www.lucd.info/2011/12/19/vsphere-5-top-10-vmfs5/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Mon, 19 Dec 2011 21:22:05 +0000</pubDate>
				<category><![CDATA[2011]]></category>
		<category><![CDATA[Dutch]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[VMFS5]]></category>
		<category><![CDATA[VMUG]]></category>
		<category><![CDATA[vSphere]]></category>
		<category><![CDATA[datastore]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=3772</guid>

					<description><![CDATA[Continuing my Dutch VMUG Event 2011 presentation series with a post on the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Continuing my <a href="https://vmug.nl/cms/index.php?option=com_content&amp;view=section&amp;layout=blog&amp;id=5&amp;Itemid=55" target="_blank">Dutch VMUG Event 2011 presentation</a> series with a post on the <strong>VMFS5</strong> feature. This feature clocked in at position 8 in the Top 10.</p>
<p>With <strong>VMFS5</strong> comes a bunch of new features. Just to name a few:</p>
<ul>
<li>64TB VMFS Volumes in 1 extent</li>
<li>64TB physical RDM</li>
<li>Unified block size of 1MB</li>
<li>Support for more files (&gt; 100000)</li>
</ul>
<p>For a complete list of the features that <strong>VMFS5</strong> introduces, have a look at <a href="https://twitter.com/#!/VMwareStorage" target="_blank">Cormac</a>&#8216;s post, called <a href="https://blogs.vmware.com/vsphere/2011/07/new-vsphere-50-storage-features-part-1-vmfs-5.html" target="_blank">vSphere 5.0 Storage Features Part 1 &#8211; VMFS-5</a>.</p>
<p><span id="more-3772"></span></p>
<p>The vSphere 5 Client has an option to upgrade your <strong>VMFS3</strong> datastores to <strong>VMFS5</strong> datastores.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/12/vmfs3-vclient-vsphere5-upgrade.png"><img loading="lazy" decoding="async" class="alignnone  wp-image-3776" title="vmfs3-vclient-vsphere5-upgrade" src="https://lucd.info/wp-content/uploads/2011/12/vmfs3-vclient-vsphere5-upgrade.png" alt="" width="566" height="182" srcset="https://www.lucd.info/wp-content/uploads/2011/12/vmfs3-vclient-vsphere5-upgrade.png 707w, https://www.lucd.info/wp-content/uploads/2011/12/vmfs3-vclient-vsphere5-upgrade-300x96.png 300w" sizes="auto, (max-width: 566px) 100vw, 566px" /></a></p>
<p>Handy option, but we want to <strong>automate</strong> this of course <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>And as a bonus I&#8217;ll throw in a function to get the <strong>partition information</strong> from a datastore.</p>
<h2>The script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function ConvertTo-Vmfs5{
&lt;#
.SYNOPSIS  Upgrade a datastore to VMFS5
.DESCRIPTION The function will convert the datastores that
  are passed to it to VMFS5.
.NOTES  Author:  Luc Dekens
.PARAMETER Datastore
  The datastore(s) to be upgraded
  The parameter accepts a string or an object returned by the
  Get-Datastore cmdlet.
.EXAMPLE
  PS&gt; ConvertTo-Vmfs5 -Datastore &quot;DS*&quot;
.EXAMPLE
  PS&gt; Get-Datastore -Name &quot;DS1&quot; | ConvertTo-Vmfs5
#&gt;

  param(
  [CmdletBinding()]
  [parameter(Mandatory = $true, ValueFromPipeline = $true)]
  [PSObject[]]$Datastore
  )

  process{
    foreach($ds in $Datastore){
      if($ds.getType().Name -eq &quot;string&quot;){
        $ds = Get-Datastore -Name $ds
      }
      $poweredHosts = $ds.ExtensionData.Host | %{Get-View -Id $_.Key} |
      where {$_.Runtime.PowerState -eq &quot;PoweredOn&quot;}
      
      $oldHost = $poweredHosts | 
      where {$_.Capability.SupportedVmfsMajorVersion -notcontains 5}
      if($oldHost){
        Write-Warning &quot;One of the connected hosts doesn't support VMFS5&quot;
        exit
      }
      $vmfsPath = $ds.ExtensionData.Host[0].MountInfo.Path
      $storSys = Get-View ($poweredHosts | Get-Random).ConfigManager.StorageSystem

      $storSys.UpgradeVmfs($vmfsPath)
    }
  }
}

function Get-VmfsPartitionInfo{
&lt;#
.SYNOPSIS  Retrieves partition info for a datastore
.DESCRIPTION The function will retrieve partition information
  for one or more datastores
.NOTES  Author:  Luc Dekens
.PARAMETER Datastore
  The datastore(s) for which the partition info shall be
  returned. The parameter accepts a string or an object
  returned by the Get-Datastore cmdlet.
.EXAMPLE
  PS&gt; Get-VmfsPartitionInfo -Datastore &quot;DS*&quot;
.EXAMPLE
  PS&gt; Get-Datastore -Name &quot;DS1&quot; | Get-VmfsPartitionInfo
#&gt;
  param(
  [CmdletBinding()]
  [parameter(Mandatory = $true, ValueFromPipeline = $true)]
  [PSObject[]]$Datastore
  )

  process{
    foreach($ds in $Datastore){
      if($ds.getType().Name -eq &quot;string&quot;){
        $ds = Get-Datastore -Name $ds
      }
      $poweredHosts = $ds.ExtensionData.Host | %{Get-View -Id $_.Key} |
      where {$_.Runtime.PowerState -eq &quot;PoweredOn&quot;}
      $storSys = Get-View ($poweredHosts | Get-Random).ConfigManager.StorageSystem

      $ds.ExtensionData.Info.Vmfs.Extent | %{
        $devicePath = &quot;/vmfs/devices/disks/&quot; + $_.DiskName
        $storSys.RetrieveDiskPartitionInfo($devicePath) | %{
          New-Object PSObject -Property @{
            Name = $ds.Name
            Version = $ds.FileSystemVersion
            Device = $_.DeviceName
            PartitionFormat = $_.Spec.PartitionFormat
            BlockSizeMB = $ds.ExtensionData.Info.Vmfs.BlockSizeMb
            Blocks = $_.Layout.Total.Block
          }
        }
      }
    }
  }
}</pre><p></p>
<h4>Annotations</h4>
<p><strong>Line 25-27</strong>: A rather simple Object By Name implementation.</p>
<p><strong>Line 28-29</strong>: Collect the hosts, connected to the datastore, that are powered on. The reason is that we can&#8217;t use the <a href="https://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.host.StorageSystem.html#upgradeVmfs" target="_blank">UpgradeVmfs</a> method via the <a href="https://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.host.StorageSystem.html#upgradeVmfs" target="_blank">StorageSystem</a> of a powered off host.</p>
<p><strong>Line 31-36</strong>: Check if all the powered on and connected hosts support VMFS5. If not, leave the function.</p>
<p><strong>Line 37</strong>: Get the devicepath to the datastore.</p>
<p><strong>Line 38</strong>: Get the HostStorageSystem. Note that the function randomly selects 1 host from the powered on hosts. There is no real reason to do this, but I wanted to spread the method call over all available hosts.</p>
<p><strong>Line 40</strong>: Convert the datastore to VMFS5</p>
<p><strong>Line 68-70</strong>: Another example of my rather simple Object By Name implementation.</p>
<p><strong>Line 71-73</strong>: We randomly take 1 of the connected hosts to fetch the HostStorageSystem.</p>
<p><strong>Line 75</strong>: We loop through each VMFS extent of the datastore</p>
<p><strong>Line 76-77</strong>: The function uses the <a href="https://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.host.StorageSystem.html#retrieveDiskPartitionInfo" target="_blank">RetrieveDiskPartitionInfo</a> method to fetch the partition information.</p>
<p><strong>Line 78-85</strong>: The function fetches the information for each partition and puts it on the pipeline as a PSObject.</p>
<h2>Sample usage</h2>
<p>In our vSphere 4 environment we have a number of VMFS3 datastores.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/12/vmfs3-cli.png"><img loading="lazy" decoding="async" class="alignnone wp-image-3777" title="vmfs3-cli" src="https://lucd.info/wp-content/uploads/2011/12/vmfs3-cli.png" alt="" width="524" height="112" srcset="https://www.lucd.info/wp-content/uploads/2011/12/vmfs3-cli.png 655w, https://www.lucd.info/wp-content/uploads/2011/12/vmfs3-cli-300x64.png 300w" sizes="auto, (max-width: 524px) 100vw, 524px" /></a></p>
<p>First, I use the <strong>Get-VmfsPartition</strong> function to check the partitioninfo of each datastore.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Datastore DS* | Get-VmfsPartitionInfo | ft -AutoSize</pre><p></p>
<p>The result.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/12/vmfs3-partition-info.png"><img loading="lazy" decoding="async" class="alignnone  wp-image-3783" title="vmfs3-partition-info" src="https://lucd.info/wp-content/uploads/2011/12/vmfs3-partition-info.png" alt="" width="600" height="102" srcset="https://www.lucd.info/wp-content/uploads/2011/12/vmfs3-partition-info.png 750w, https://www.lucd.info/wp-content/uploads/2011/12/vmfs3-partition-info-300x50.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></p>
<p>Notice the <strong>BlockSizeMB</strong> column in the output, all 4 possible blocksizes for VMFS3 datastores are present.</p>
<p>Let&#8217;s upgrade these VMFS3 datastores to VMFS5 datastores.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Datastore DS* | ConvertTo-Vmfs5</pre><p></p>
<p>The convert function produces no output, but we can check what the new properties are with the <strong>Get-VmfsPartitionInfo</strong> function.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/12/vmfs5-partition-info.png"><img loading="lazy" decoding="async" class="alignnone  wp-image-3785" title="vmfs5-partition-info" src="https://lucd.info/wp-content/uploads/2011/12/vmfs5-partition-info.png" alt="" width="618" height="105" srcset="https://www.lucd.info/wp-content/uploads/2011/12/vmfs5-partition-info.png 772w, https://www.lucd.info/wp-content/uploads/2011/12/vmfs5-partition-info-300x50.png 300w" sizes="auto, (max-width: 618px) 100vw, 618px" /></a></p>
<p>The VMFS version is <strong>5.54</strong>, so the conversion worked.</p>
<p>But the attentive viewer might have noticed a couple of values he didn&#8217;t expect.</p>
<ul>
<li>The PartitionFormat still says &#8216;MBR&#8217;. Shouldn&#8217;t that be &#8216;GPT&#8217; ?</li>
<li>The BlocksizeMB stayed the same as before the VMFS5 conversion. Shouldn&#8217;t that be 1MB for VMFS5 datastores ?</li>
</ul>
<p>The answer to both questions can be found in Cormac&#8217;s post called <a href="https://blogs.vmware.com/vsphere/2011/07/new-vsphere-50-storage-features-part-1-vmfs-5.html" target="_blank">vSphere 5.0 Storage Features Part 1 &#8211; VMFS-5</a>.</p>
<ul>
<li>A converted datastores keeps the &#8216;MBR&#8217; format until it grows bigger than 2TB.</li>
<li>A converted datastores keeps the original VMFS3 blocksize.</li>
</ul>
<p>And I want to repeat Cormac&#8217;s final advise in his post, if you have the luxury to do so, it&#8217;s better to create new VMFS5 datastores instead of converting VMFS3 datastores !</p>
<h2>VIProperty</h2>
<p>Derived from the <strong>Get-VmfsPartitionInfo</strong> function, I created a <strong>New-VIProperty</strong> definition to return the format of the first datastore partition.</p><pre class="urvanov-syntax-highlighter-plain-tag">New-VIProperty -Name PartitionFormat -ObjectType Datastore `
  -Value {
    param($ds)

    $storSys = Get-View (Get-View $ds.ExtensionData.Host[0].Key).ConfigManager.StorageSystem
    $partInfo = $storSys.RetrieveDiskPartitionInfo(&quot;/vmfs/devices/disks/&quot; + 
      $ds.ExtensionData.Info.Vmfs.Extent[0].DiskName)
    $partInfo[0].Spec.PartitionFormat
  } -Force | Out-Null</pre><p>Note that you will only get the partition format (MBR or GPT) when you use this in a vSphere 5, or higher, environment. The <strong>partitionFormat</strong> property in the <a href="https://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.host.DiskPartitionInfo.Specification.html" target="_blank">HostDiskPartitionSpec</a> object is only available since API 5.</p>
<p>Enjoy !</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2011/12/19/vsphere-5-top-10-vmfs5/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>vSphere 5 Top 10 – HA</title>
		<link>https://www.lucd.info/2011/12/13/vsphere-5-top-10-%e2%80%93-ha/</link>
					<comments>https://www.lucd.info/2011/12/13/vsphere-5-top-10-%e2%80%93-ha/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Tue, 13 Dec 2011 21:22:15 +0000</pubDate>
				<category><![CDATA[2011]]></category>
		<category><![CDATA[datastore]]></category>
		<category><![CDATA[Dutch]]></category>
		<category><![CDATA[HA]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[VMUG]]></category>
		<category><![CDATA[vSphere]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=3715</guid>

					<description><![CDATA[The second post originating from our presentation at the Dutch VMUG Event 2011 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The second post originating from our presentation at the <a href="https://vmug.nl/cms/index.php?option=com_content&amp;view=section&amp;layout=blog&amp;id=5&amp;Itemid=55" target="_blank">Dutch VMUG Event 2011</a> is about HA. vSphere <strong>High Availability</strong> appeared in the 2nd place of the <strong>vSphere 5 features Top 10</strong>. For the HA feature we showed how you could find out the <strong>FDM</strong> master and slaves in your cluster, and how to find the <strong>heartbeat datastore</strong>.</p>
<p style="padding-left: 150px;"><a href="https://lucd.info/wp-content/uploads/2011/12/FDM.jpg"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3716" title="FDM" src="https://lucd.info/wp-content/uploads/2011/12/FDM.jpg" alt="" width="234" height="291" /></a></p>
<h2><span id="more-3715"></span>The FDM roles</h2>
<p>The following script will show,for each cluster node, which FDM role it holds.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-DasHostState{
  param(
  [PSObject]$Cluster
  )

  if($Cluster.GetType().Name -eq &quot;string&quot;){
    $Cluster = Get-Cluster -Name $Cluster
  }
  Get-View $cluster.ExtensionData.Host -Property Name,Runtime.DasHostState | %{
    New-Object PSObject -Property @{
      VMHost = $_.Name
      DasHostState = $_.RunTime.DasHostState.State
      StateReporter = (Get-View -Id $_.RunTime.DasHostState.StateReporter -Property Name).Name
    }
  }
}</pre><p></p>
<p>To call the function you can pass a clustername or the output of a Get-Cluster cmdlet. Something like this.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-DasHostState -Cluster Cluster1</pre><p></p>
<p>or this</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">$clus = Get-Cluster -Name Cluster1
Get-DasHostState -Cluster $clus</pre><p></p>
<p>The output looks like this</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/12/HA-FDM-report.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3718" title="HA-FDM-report" src="https://lucd.info/wp-content/uploads/2011/12/HA-FDM-report.png" alt="" width="582" height="88" srcset="https://www.lucd.info/wp-content/uploads/2011/12/HA-FDM-report.png 727w, https://www.lucd.info/wp-content/uploads/2011/12/HA-FDM-report-300x45.png 300w" sizes="auto, (max-width: 582px) 100vw, 582px" /></a></p>
<p>Note that there are more <strong>DasHostState</strong> values, besides <strong>master</strong> and <strong>connectedToMaster</strong>, possible. The complete list can be found in the <a href="https://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.cluster.DasFdmAvailabilityState.html" target="_blank">ClusterDasFdmAvailabilityState</a> enumeration.</p>
<p>And you can of course provide this functionality as a New-VIProperty.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VIProperty -Name &quot;DasHostState&quot; -ObjectType Cluster -Value {
  param($cluster)

  Get-View $cluster.ExtensionData.Host -Property Name,Runtime.DasHostState | %{
    New-Object PSObject -Property @{
      VMHost = $_.Name
      DasHostState = $_.RunTime.DasHostState.State
      StateReporter = (Get-View -Id $_.RunTime.DasHostState.StateReporter).Name
    }
  }
} -Force | Out-Null</pre><p></p>
<p>Now you can find the FDM states with a call like this</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Cluster -Name London | Select -ExpandProperty DasHostState</pre><p></p>
<p>The output will look exactly the same as the output that comes out of the Get-DasHostState function.</p>
<h2>The heartbeat datastore</h2>
<p>Another HA novelty in vSphere 5 is that it will now use, besides a network-based heartbeat, a datastore heartbeat, to check the presence of the nodes. To find out which of the shared datastores is used as the heartbeat datastore, you can use the following function.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-DasHostState{
  param(
  [PSObject]$Cluster
  )

  if($Cluster.GetType().Name -eq &quot;string&quot;){
    $Cluster = Get-Cluster -Name $Cluster
  }

  $cluster.ExtensionData.RetrieveDasAdvancedRuntimeInfo()  | %{
    $_.HeartbeatDatastoreInfo | %{
      New-Object PSObject -Property @{
        Datastore = (Get-View -Id $_.Datastore).Name
        VMHosts = [string]::Join(',',($_.Hosts | %{(Get-View -Id $_).Name}))
      }
    }
  }
}</pre><p></p>
<p>The function can be called again with the name of a cluster or with the object returned by the Get-Cluster cmdlet.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-DasHostState -Cluster Cluster1</pre><p></p>
<p>The output looks something like this.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/12/HA-DS-report.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3727" title="HA-DS-report" src="https://lucd.info/wp-content/uploads/2011/12/HA-DS-report.png" alt="" width="452" height="62" srcset="https://www.lucd.info/wp-content/uploads/2011/12/HA-DS-report.png 565w, https://www.lucd.info/wp-content/uploads/2011/12/HA-DS-report-300x40.png 300w" sizes="auto, (max-width: 452px) 100vw, 452px" /></a></p>
<p>And of course, the same functionality as a New-VIProperty.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">New-VIProperty -Name HeartbeatDatastore -ObjectType Cluster -Value {
  param($cluster)

  $cluster.ExtensionData.RetrieveDasAdvancedRuntimeInfo() | %{
    [String]::Join(',',($_.HeartbeatDatastoreInfo |
    %{(Get-View -Id $_.Datastore).Name}))
  }
} -Force | Out-Null</pre><p></p>
<p>You can now use the <strong>HeartbeatDatastore</strong> property to get the datastore that is used for the heartbeat.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Cluster -Name Cluster1 | Select Name, HeartbeatDatastore</pre><p></p>
<p>Which will result in</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/12/HA-DS-New-VIProperty-report.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3730" title="HA-DS-New-VIProperty-report" src="https://lucd.info/wp-content/uploads/2011/12/HA-DS-New-VIProperty-report.png" alt="" width="597" height="71" srcset="https://www.lucd.info/wp-content/uploads/2011/12/HA-DS-New-VIProperty-report.png 746w, https://www.lucd.info/wp-content/uploads/2011/12/HA-DS-New-VIProperty-report-300x35.png 300w" sizes="auto, (max-width: 597px) 100vw, 597px" /></a></p>
<p>Enjoy !</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2011/12/13/vsphere-5-top-10-%e2%80%93-ha/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Storage Views &#8211; Datastores</title>
		<link>https://www.lucd.info/2011/11/14/storage-views-datastores/</link>
					<comments>https://www.lucd.info/2011/11/14/storage-views-datastores/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Mon, 14 Nov 2011 19:58:06 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Storage Views]]></category>
		<category><![CDATA[VMDK]]></category>
		<category><![CDATA[report]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=3651</guid>

					<description><![CDATA[In the vCenter Client, since vSphere 4, you can find a Storage Views [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In the vCenter Client, since <strong>vSphere 4</strong>, you can find a <strong>Storage Views</strong> tab on several of the VI containers. The data in these Storage Views is collected and provided by the <strong>vCenter Storage Monitoring</strong> plug-in.</p>
<p>Have a look at <a href="https://www.twitter.com/davidmdavis" target="_blank" rel="noopener noreferrer">David Davis</a>&#8216;s post, called <a href="http://www.virtualizationadmin.com/articles-tutorials/vmware-esx-and-vsphere-articles/storage-management/using-vmware-vsphere-storage-views.html" target="_blank" rel="noopener noreferrer">Using VMware vSphere Storage Views</a>, for more information on what you can do with the Storage Views.</p>
<p>Some time ago I got a question from Andrew how the <strong>Multipathing Status</strong> presented in the Storage Views could be detected and reported upon by a PowerCLI script. What looked rather simple at first, turned out to be a bit more difficult than I anticipated.</p>
<p><span id="more-3651"></span></p>
<p>The primary reason I created this function, is that it will allow to schedule the creation of the Storage Views &#8211; Datastores values at regular intervals. A feature that is unfortunately missing from the vCenter Client plug-in.</p>
<p>With those saved values it is easy to produce reports that show who is consuming the storage over time.</p>
<h2>The script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-StorageViewDatastore{
&lt;#
.SYNOPSIS  Retrieve the &quot;Storage Views - Show all Datastores&quot; values
.DESCRIPTION The function calculates and returns all the values
  that you get in the Storage Views - Show all Datastores panel.
.NOTES  Author:  Luc Dekens
.PARAMETER VMHost
  Specify the ESX(i) server for which you want to retrieve
  the Storage Views values.
.PARAMETER Cluster
  Specify the Cluster for which you want to retrieve
  the Storage Views values.
.PARAMETER Datacenter
  Specify the Datacenter for which you want to retrieve
  the Storage Views values.
.PARAMETER VM
  Specify the VM for which you want to retrieve
  the Storage Views values.
.PARAMETER ResourcePool
  Specify the ResourcePool for which you want to retrieve
  the Storage Views values.
.EXAMPLE
  PS&gt; Get-StorageViewDatastore -VMHost MyCluster
.EXAMPLE
  PS&gt; Get-Datacenter MyDC | Get-StorageViewDatastore
#&gt;

  [CmdletBinding()]
  param(
  [parameter(ParameterSetName=&quot;VMHost&quot;,Mandatory = $true)]
  [PSObject]$VMHost,
  [parameter(ParameterSetName=&quot;Cluster&quot;,Mandatory = $true)]
  [PSObject]$Cluster,
  [parameter(ParameterSetName=&quot;Datacenter&quot;,Mandatory = $true)]
  [PSObject]$Datacenter,
  [parameter(ParameterSetName=&quot;VM&quot;,Mandatory = $true)]
  [PSObject]$VM,
  [parameter(ParameterSetName=&quot;ResourcePool&quot;,Mandatory = $true)]
  [PSObject]$ResourcePool
  )

  process{
    # Get the datastores and ESX(i) servers
    switch($PSCmdlet.ParameterSetName){
      &quot;Datacenter&quot; {
        if($Datacenter.GetType().Name -eq &quot;String&quot;){
          $Datacenter = Get-Datacenter -Name $Datacenter
        }
        $vms = Get-VM -Location $Datacenter
        $esx = Get-VMHost -Location $Datacenter
        $datastores = Get-Datastore -VMHost $esx
      }
      &quot;Cluster&quot; {
        if($Cluster.GetType().Name -eq &quot;String&quot;){
          $Cluster = Get-Cluster -Name $Cluster
        }
        $vms = Get-VM -Location $cluster
        $esx = Get-VMHost -Location $Cluster
        $datastores = Get-Datastore -VMHost $esx
      }
      &quot;VMHost&quot; {
        if($VMHost.GetType().Name -eq &quot;String&quot;){
          $VMHost = Get-VMHost -Name $VMHost
        }
        $vms = Get-VM -Location $VMHost
        $esx = $VMHost
        $datastores = Get-Datastore -VMHost $VMHost
      }
      &quot;VM&quot; {
        if($VM.GetType().Name -eq &quot;String&quot;){
          $VM = Get-VM -Name $VM
        }
        $vms = $vm
        $esx = $vm.VMHost
        $datastores = Get-Datastore -Name ($vms | Get-HardDisk -DiskType flat | %{$_.Filename.Split(']')[0].TrimStart('[')} | Sort-Object -Unique) | Sort-Object -Property Name
      }
      &quot;ResourcePool&quot; {
        if($ResourcePool.GetType().Name -eq &quot;String&quot;){
          $ResourcePool = Get-ResourcePool -Name $ResourcePool
        }
        $vms = Get-VM -Location $ResourcePool
        $esx = $vms  | %{$_.VMHost} | Sort-Object -Property Name -Unique
        $datastores = Get-Datastore -Name ($vms | Get-HardDisk -DiskType flat | %{$_.Filename.Split(']')[0].TrimStart('[')} | Sort-Object -Unique) | Sort-Object -Property Name
      }
    }

    # Create some helper collections
    $esxMoRef = $esx | %{$_.ExtensionData.MoRef}
    $vmMoRef = $vms | %{$_.ExtensionData.MoRef}

    # Set up a HBA hash table
    $hbaFCNodeWWN = @{}
    Get-VMHostHba -VMHost $esx -Type FibreChannel | %{
      $hbaFCNodeWWN[&quot;{0:X}&quot; -f $_.NodeWorldWideName] = 0
    }

    # Handle all datastores
    foreach($ds in $datastores){
      $mpStatus = $usedSpace = $snapSpace = &quot;&quot;
      if($ds.Type -eq &quot;VMFS&quot;){
        $lun = $ds.ExtensionData.Info.Vmfs.Extent | %{$_.DiskName} |
          %{Get-ScsiLun -CanonicalName $_ -VmHost $esx -ErrorAction SilentlyContinue}
        $hbaFCCopy = $hbaFCNodeWWN.Clone()
        # Count Active and Standby paths
        # If there are 2 or more paths, the multi-path status is fully redundant
        Get-ScsiLunPath -ScsiLun $lun | where {&quot;Active&quot; ,&quot;Standby&quot; -contains $_.State} | %{
          $hbaFCCopy[$_.LunPath.Split(':')[0].Split('.')[1]] += 1
        }
        if(($hbaFCCopy.Values | where {$_} | Measure-Object).Count -gt 1){
          $mpStatus = &quot;Full Redundancy&quot;
        }
        else{
          $mpStatus = &quot;Partial/No Redundancy&quot;
        }
      }

      # Get the total used, snapshot, swap, shared and other space
      $usedSpace = 0
      $snapSpace = 0
      $vdiskSpace = 0
      $swapSpace = 0
      $otherSpace = 0
      $sharedSpace = 0
      if($ds.ExtensionData.Vm){
        Get-View $ds.ExtensionData.Vm | where {$vmMoRef -contains $_.MoRef -and $esxMoRef -contains $_.Runtime.Host} | %{
          $snapIndex = @()
          $dsPattern = '\[' + $ds.Name + '\]'
          $usedSpace += ($_.Storage.PerDatastoreUsage | where {$_.Datastore -eq $ds.ExtensionData.MoRef}).Committed
          if($_.LayoutEx.Snapshot){
            $snapIndex = $_.layoutEx.Disk | %{$_.Chain[1..($_.Chain.Count - 1)]} | %{$_.FileKey}
          }
          $snapIndex += $_.layoutEx.File | where {&quot;snapshotList&quot;,&quot;snapshotData&quot; -contains $_.Type -and $_.Name -match $dsPattern} | %{$_.Key}
          if($snapIndex){
            $snapSpace += ($_.LayoutEx.File | where {$snapIndex -contains $_.Key -and $_.Name -match $ds.Name} | Measure-Object -Property Size -Sum).Sum
          }
          $vdiskIndex = $_.layoutEx.File | where {&quot;diskDescriptor&quot;,&quot;diskExtent&quot; -contains $_.Type -and $_.Name -match $dsPattern} | %{$_.Key}
          if($vdiskIndex){
            $vdiskSpace += ($_.LayoutEx.File | where {$vdiskIndex -contains $_.Key} | Measure-Object -Property Size -Sum).Sum
          }
          $swapIndex = $_.LayoutEx.File | where {$_.Type -eq &quot;swap&quot; -and $_.Name -match $dsPattern} | %{$_.Key}
          if($swapIndex){
            $swapSpace += ($_.LayoutEx.File | where {$swapIndex -contains $_.Key} | Measure-Object -Property Size -Sum).Sum
          }
          $otherIndex = $_.LayoutEx.File | where {&quot;log&quot;,&quot;config&quot;,&quot;extendedConfig&quot;,&quot;nvram&quot;,&quot;core&quot; -contains $_.Type -and $_.Name -match $dsPattern} | %{$_.Key}
          if($otherIndex){
            $otherSpace += ($_.LayoutEx.File | where {$otherIndex -contains $_.Key} | Measure-Object -Property Size -Sum).Sum
          }
          $vmds = $_.Storage.PerDatastoreUsage | where {$_.Datastore -eq $ds.ExtensionData.MoRef}
          if($vmds){
            $sharedSpace += ($vmds.Committed - $vmds.Unshared)
          }
        }
      }

      # Collect all values for Storage Views - Datastores
      New-Object PSObject -Property @{
        VMHost = $esx.Name
        Datastore = $ds.Name
        &quot;File System Type&quot; = $ds.Type.Replace(&quot;NFS&quot;,&quot;NAS&quot;)
        &quot;Connectivity Status&quot; = &amp;{if($ds.Accessible){&quot;Up&quot;}else{&quot;Down&quot;}}
        &quot;Multipathing Status&quot; = $mpStatus
        Capacity = Get-FriendlyUnit -Value ($ds.CapacityMB * 1MB)
        Free = Get-FriendlyUnit -Value ($ds.FreeSpaceMB * 1MB)
        Used = Get-FriendlyUnit -Value $usedSpace
        Snapshot = Get-FriendlyUnit -Value $snapSpace
        vDisk = Get-FriendlyUnit -Value ($vdiskSpace - $snapSpace)
        Swap = Get-FriendlyUnit -Value $swapSpace
        Other = Get-FriendlyUnit -Value $otherSpace
        Shared = Get-FriendlyUnit -Value $sharedSpace
      }
    }
  }
}</pre><p></p>
<h4>Annotations</h4>
<p><strong>Line 29-40</strong>: The function uses <strong>5 parameter sets</strong> that allow you to get the Storage Views &#8211; Datastores values for a VM, an ESX(i) server, a ResourcePool, a Cluster or a Datacenter.</p>
<p><strong>Line 44-85</strong>: For each of the parameter sets, this Switch block calculates the VMs, the ESX(i) host(s) and the datastore(s) that need to be queried. Notice that each of the 5 parameter sets support a kind of Object By Name (OBN), that means you can pass the name or the object itself.</p>
<p><strong>Line 88-89</strong>: The script will use these MoRef collections later on to determine if a specific VM needs to be included in the calculations for the Storage Views values.</p>
<p><strong>Line 92-95</strong>: To determine the Multipathing Status the script first creates a hash table for all the FC HBAs in the ESX(i) servers. The key for this hash table is the WWN, in hex format, for the HBA.</p>
<p><strong>Line 98-171</strong>: The main loop over all the datastores that the script needs to handle.</p>
<p><strong>Line 101-102</strong>: The script collects all the LUNs that are part of the datastore.</p>
<p><strong>Line 103</strong>: The Multipathing logic works with a copy of the hash table that was created earlier.</p>
<p><strong>Line 106-108</strong>: In the hash table the script increments the value for each LUN path that is Active or Standby.</p>
<p><strong>Line 109-114</strong>: If a LUN has more then 1 path, the <strong>Multipathing Status</strong> is considered as <strong>Full Redundancy</strong>. Otherwise the status is <strong>Partial/No Redundancy</strong>.</p>
<p><strong>Line 118-153</strong>: The script calculates all values that are related to the storage in use by the VMs.</p>
<p><strong>Line 125</strong>: For a VM to be taken into account, the VM must use storage on the datastore and must be hosted by one of the ESX(i) host.</p>
<p><strong>Line 127</strong>: This Regular Expression will be used later on to verify the a specific file is located on the datastore. Note that the square brackets need to be escaped.</p>
<p><strong>Line 128</strong>: The Space Used value is the sum of all the Committed space for each of the VMs on that datastore.</p>
<p><strong>Line 129-135</strong>: The space used by snapshots is the sum of all the VMDK snapshot files and the snapshotList and the snapshotData files.</p>
<p><strong>Line 132</strong>: Note that we check for each file used for the Snapshot Space calculation, if it is located on the datastore with the -match operator. This is required since the administrator or user can define that snapshot files need to be stored on another datastore.</p>
<p><strong>Line 136-139</strong>: All the files used for the vDisks of a VM.</p>
<p><strong>Line 140-143</strong>: All swap related files</p>
<p><strong>Line 144-147</strong>: All other files that are used by the VM.</p>
<p><strong>Line 148-151</strong>: This block calculates the Shared Space for a VM. Examples of shared space usage are linked clones that are created from a snapshot with the createNewChildDiskBacking option for the diskMoveType (see the <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html" target="_blank" rel="noopener noreferrer">VirtualMachineRelocateSpec</a>).</p>
<p><strong>Line 156-170</strong>: Create the object, per datastore, with all the values. To have similar values that are presented in the Storage Views panel, the script uses the <strong>Get-FriendlyUnits</strong> function from my <a href="https://www.lucd.info/2011/11/06/friendly-units/" target="_blank" rel="noopener noreferrer">Friendly Units</a> post.</p>
<p><strong>Line 166</strong>: Note that for the Virtual Disk Space value we need to subtract the Snapshot Space from the total disk space.</p>
<h2>Samples</h2>
<p>You can pass the function the name of the object for which you want the Storage Views &#8211; Datastore values.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-StorageViewDatastore -Cluster MyCluster |
Select-Object Datastore,&quot;File System Type&quot;,&quot;Connectivity Status&quot;,&quot;Multipathing Status&quot;,
  @{N=&quot;Capacity&quot;;E={&quot;{0,7:f2} {1,2}&quot; -f $_.Capacity.Value,$_.Capacity.Unit}},
  @{N=&quot;Free Space&quot;;E={&quot;{0,7:f2} {1,2}&quot; -f $_.Free.Value,$_.Free.Unit}},
  @{N=&quot;Space Used&quot;;E={if($_.Used.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Used.Value,$_.Used.Unit}}},
  @{N=&quot;Snapshot Space&quot;;E={if($_.Snapshot.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Snapshot.Value,$_.Snapshot.Unit}}},
  @{N=&quot;Virtual Disk Space&quot;;E={if($_.vDisk.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.vDisk.Value,$_.vDisk.Unit}}},
  @{N=&quot;Swap Space&quot;;E={if($_.Swap.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Swap.Value,$_.Swap.Unit}}},
  @{N=&quot;Other VM Space&quot;;E={if($_.Other.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Other.Value,$_.Other.Unit}}},
  @{N=&quot;Shared Space&quot;;E={if($_.Shared.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Shared.Value,$_.Shared.Unit}}} |
Format-Table -AutoSize</pre><p></p>
<p>Or you can pass the actual object.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">$dc = Get-Datacenter -Name MyDC
Get-StorageViewDatastore -Datacenter $dc |
Select-Object Datastore,&quot;File System Type&quot;,&quot;Connectivity Status&quot;,&quot;Multipathing Status&quot;,
  @{N=&quot;Capacity&quot;;E={&quot;{0,7:f2} {1,2}&quot; -f $_.Capacity.Value,$_.Capacity.Unit}},
  @{N=&quot;Free Space&quot;;E={&quot;{0,7:f2} {1,2}&quot; -f $_.Free.Value,$_.Free.Unit}},
  @{N=&quot;Space Used&quot;;E={if($_.Used.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Used.Value,$_.Used.Unit}}},
  @{N=&quot;Snapshot Space&quot;;E={if($_.Snapshot.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Snapshot.Value,$_.Snapshot.Unit}}},
  @{N=&quot;Virtual Disk Space&quot;;E={if($_.vDisk.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.vDisk.Value,$_.vDisk.Unit}}},
  @{N=&quot;Swap Space&quot;;E={if($_.Swap.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Swap.Value,$_.Swap.Unit}}},
  @{N=&quot;Other VM Space&quot;;E={if($_.Other.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Other.Value,$_.Other.Unit}}},
  @{N=&quot;Shared Space&quot;;E={if($_.Shared.Value){&quot;{0,7:f2} {1,2}&quot; -f $_.Shared.Value,$_.Shared.Unit}}} |
Export-Csv &quot;C:\SV-MyDC.csv&quot; -NoTypeInformation -UseCulture</pre><p></p>
<p>The previous example also showed how the results can be saved to a CSV file.<br />
Such a CSV file looks as follows.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/11/SV-DS1.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3663" title="SV-DS1" src="https://lucd.info/wp-content/uploads/2011/11/SV-DS1.png" alt="" width="925" height="174" srcset="https://www.lucd.info/wp-content/uploads/2011/11/SV-DS1.png 1321w, https://www.lucd.info/wp-content/uploads/2011/11/SV-DS1-300x56.png 300w, https://www.lucd.info/wp-content/uploads/2011/11/SV-DS1-1024x193.png 1024w" sizes="auto, (max-width: 925px) 100vw, 925px" /></a></p>
<p>Enjoy the function !</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2011/11/14/storage-views-datastores/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title>Datastore usage statistics</title>
		<link>https://www.lucd.info/2011/06/19/datastore-usage-statistics/</link>
					<comments>https://www.lucd.info/2011/06/19/datastore-usage-statistics/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Sun, 19 Jun 2011 21:51:29 +0000</pubDate>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[statistics]]></category>
		<guid isPermaLink="false">http://www.lucd.info/?p=3306</guid>

					<description><![CDATA[An interesting question came up in the PowerCLI Community. Can one extract the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>An interesting <a href="https://communities.vmware.com/thread/315887?tstart=0" target="_blank">question</a> came up in the PowerCLI Community. Can one extract the datastore statistics, that are used for the space utilization graphs in the vSphere Client, with PowerCLI ? The graph in question, which you find in the Datastores Inventory view under the Performance tab, looks something like this.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/06/DS-stat3.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3311" title="DS-stat3" src="https://lucd.info/wp-content/uploads/2011/06/DS-stat3.png" alt="" width="414" height="312" srcset="https://www.lucd.info/wp-content/uploads/2011/06/DS-stat3.png 517w, https://www.lucd.info/wp-content/uploads/2011/06/DS-stat3-300x226.png 300w" sizes="auto, (max-width: 414px) 100vw, 414px" /></a></p>
<p><span id="more-3306"></span>A quick browse through the available metrics, on the SDK Reference <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.PerformanceManager.html" target="_blank">PerformanceManager</a> page, showed that these metrics are indeed available.</p>
<p>With the <strong>disk.capacity.latest</strong>, <strong>disk.provisioned.latest</strong> and <strong>disk.used.latest</strong> metrics this should be a simple script. But was it ? As it turned out there are a few gotchas!</p>
<h2>Getting there</h2>
<p>The SDK Reference, on the <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/disk_storutil_counters.html" target="_parent">Storage Capacity page</a>, mentions that these metrics are available for <strong>virtual machines</strong> and for <strong>datastores</strong>. In this case we obviously want the metrics for the datastore.</p>
<h3>Get-Stat doesn&#8217;t do datastores.</h3>
<p>Which brings us immediately to the first problem, the current <a href="https://www.vmware.com/support/developer/PowerCLI/PowerCLI41U1/html/Get-Stat.html" target="_blank">Get-Stat</a> cmdlet doesn&#8217;t accept <strong>datastore</strong> entities. No problem, I have an older post, called <a href="https://communities.vmware.com/docs/DOC-10384" target="_blank">Get-Stat2 : another way of getting at the statistical data</a>, which I should be able to adapt to retrieve datastore statistics.</p>
<p>The script uses a number of methods on the <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.PerformanceManager.html" target="_blank">PerformanceManager</a> object, to retrieve the counterId and available instances for the metrics. Once it has these it calls the <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.PerformanceManager.html#queryStats" target="_blank">QueryPerf</a> method to get the actual statistical data.</p>
<p>Next problem!</p>
<h3>The &#8220;optional value not set&#8221; error</h3>
<p>On each call I seemed to get an error, stating &#8220;optional value not set&#8221;. A quick search through the VMTN posts showed that I was not the first one seeing that error when using datastore metrics. Unfortunately none of these posts provided me with a workable solution.</p>
<p>After some trial and error, I discovered that the problem was caused by the <strong>intervalId</strong> property. Although the SDK Reference states that you can either use <strong>begintime</strong>/<strong>endtime</strong> or <strong>intervalId</strong>, it seems that for datastores the PerformanceManager methods only want you to use <strong>beginTime</strong> and <strong>endTime</strong>.</p>
<p>This required some fundamental changes to the Get-Stat2 script, but in the end I got it working.</p>
<h3>Instances. What instances ?</h3>
<p>As with most metrics, you have the option to use the <strong>instance</strong> property, to identify which specific statistical data you want to retrieve. According to the SDK Reference page, the Storage Capacity metrics support the following instances.</p>
<table border="0">
<tbody>
<tr>
<td>Counter</td>
<td>Instance</td>
<td>Result</td>
</tr>
<tr>
<td>disk.capacity.latest</td>
<td>&lt;empty&gt;</td>
<td>Capacity, in KB, for the complete datastore</td>
</tr>
<tr>
<td>disk.provisioned.latest</td>
<td>&lt;empty&gt;</td>
<td>Provisioned space, in KBm for the complete datastore</td>
</tr>
<tr>
<td></td>
<td>VMid</td>
<td>Provisioned space, in KB, for a specific virtual machine</td>
</tr>
<tr>
<td>disk.unshared.latest</td>
<td>VMid</td>
<td>Unshared space, in KB, per virtual machine on the datastore</td>
</tr>
<tr>
<td>disk.used.latest</td>
<td>&lt;empty&gt;</td>
<td>Actually used space, in KB, on the datastore</td>
</tr>
<tr>
<td></td>
<td>VMid</td>
<td>Actually used space, in KB, for a specific virtual machine</td>
</tr>
<tr>
<td></td>
<td>&#8220;DISKFILE&#8221;</td>
<td>Actually used space, in KB,</td>
</tr>
<tr>
<td></td>
<td>&#8220;DELTAFILE&#8221;</td>
<td>Actually used space, in KB, for snapshot files</td>
</tr>
<tr>
<td></td>
<td>&#8220;SWAPFILE&#8221;</td>
<td>Actually used space, in KB, for the swap files</td>
</tr>
<tr>
<td></td>
<td>&#8220;OTHERFILE&#8221;</td>
<td>Actually used space, in KB, for all other virtual machine related files</td>
</tr>
</tbody>
</table>
<p>The VMid is the <strong>value</strong> property of the <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vmodl.ManagedObjectReference.html" target="_blank">MoRef</a> of a specific virtual machine.</p>
<h2>The script</h2>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">function Get-Stat2 {
&lt;#
.SYNOPSIS  Retrieve vSphere statistics
.DESCRIPTION The function is an alternative to the Get-Stat cmdlet.
  It's primary use is to provide functionality that is missing
  from the Get-Stat cmdlet.
.NOTES  Author:  Luc Dekens
.PARAMETER Entity
  Specify the VIObject for which you want to retrieve statistics
  This needs to be an SDK object
.PARAMETER Start
  Start of the interval for which to retrive statistics
.PARAMETER Finish
  End of the interval for which to retrive statistics
.PARAMETER Stat
  The identifiers of the metrics to retrieve
.PARAMETER Instance
  The instance property of the statistics to retrieve
.PARAMETER Interval
  Specify for which interval you want to retrieve statistics.
  Allowed values are RT, HI1, HI2, HI3 and HI4
.PARAMETER MaxSamples
  The maximum number of samples for each metric
.PARAMETER QueryMetrics
  Switch to indicate that the function should return the available
  metrics for the Entity specified
.PARAMETER QueryInstances
  Switch to indicate that the function should return the valid instances
  for a specific Entity and Stat
.EXAMPLE
  PS&gt; Get-Stat2 -Entity $vm.Extensiondata -Stat &quot;cpu.usage.average&quot; -Interval &quot;RT&quot;
#&gt;

  [CmdletBinding()]
  param (
  [parameter(Mandatory = $true,  ValueFromPipeline = $true)]
  [PSObject]$Entity,
  [DateTime]$Start,
  [DateTime]$Finish,
  [String[]]$Stat,
  [String]$Instance = &quot;&quot;,
  [ValidateSet(&quot;RT&quot;,&quot;HI1&quot;,&quot;HI2&quot;,&quot;HI3&quot;,&quot;HI4&quot;)]
  [String]$Interval = &quot;RT&quot;,
  [int]$MaxSamples,
  [switch]$QueryMetrics,
  [switch]$QueryInstances)

  # Test if entity is valid
  $EntityType = $Entity.GetType().Name

  if(!((&quot;HostSystem&quot;,
        &quot;VirtualMachine&quot;,
        &quot;ClusterComputeResource&quot;,
        &quot;Datastore&quot;,
        &quot;ResourcePool&quot;) -contains $EntityType)) {
    Throw &quot;-Entity parameters should be of type HostSystem, VirtualMachine, ClusterComputeResource, Datastore or ResourcePool&quot;
  }

  $perfMgr = Get-View (Get-View ServiceInstance).content.perfManager

  # Create performance counter hashtable
  $pcTable = New-Object Hashtable
  $keyTable = New-Object Hashtable
  foreach($pC in $perfMgr.PerfCounter){
    if($pC.Level -ne 99){
      if(!$pctable.containskey($pC.GroupInfo.Key + &quot;.&quot; + $pC.NameInfo.Key + &quot;.&quot; + $pC.RollupType)){
        $pctable.Add(($pC.GroupInfo.Key + &quot;.&quot; + $pC.NameInfo.Key + &quot;.&quot; + $pC.RollupType),$pC.Key)
        $keyTable.Add($pC.Key, $pC)
      }
    }
  }

  # Test for a valid $Interval
  if($Interval.ToString().Split(&quot; &quot;).count -gt 1){
    Throw &quot;Only 1 interval allowed.&quot;
  }

  $intervalTab = @{&quot;RT&quot;=$null;&quot;HI1&quot;=0;&quot;HI2&quot;=1;&quot;HI3&quot;=2;&quot;HI4&quot;=3}
  $dsValidIntervals = &quot;HI2&quot;,&quot;HI3&quot;,&quot;HI4&quot;
  $intervalIndex = $intervalTab[$Interval]

  if($EntityType -ne &quot;datastore&quot;){
    if($Interval -eq &quot;RT&quot;){
      $numinterval = 20
    }
    else{
      $numinterval = $perfMgr.HistoricalInterval[$intervalIndex].SamplingPeriod
    }
  }
  else{
    if($dsValidIntervals -contains $Interval){
      $numinterval = $null
      if(!$Start){
        $Start = (Get-Date).AddSeconds($perfMgr.HistoricalInterval[$intervalIndex].SamplingPeriod - $perfMgr.HistoricalInterval[$intervalIndex].Length)
      }
      if(!$Finish){
        $Finish = Get-Date
      }
    }
    else{
      Throw &quot;-Interval parameter $Interval is invalid for datastore metrics.&quot;
    }
  }

  # Test if QueryMetrics is given
  if($QueryMetrics){
    $metrics = $perfMgr.QueryAvailablePerfMetric($Entity.MoRef,$null,$null,$numinterval)
    $metricslist = @()
    foreach($pmId in $metrics){
      $pC = $keyTable[$pmId.CounterId]
      $metricslist += New-Object PSObject -Property @{
        Group = $pC.GroupInfo.Key
        Name = $pC.NameInfo.Key
        Rollup = $pC.RollupType
        Id = $pC.Key
        Level = $pC.Level
        Type = $pC.StatsType
        Unit = $pC.UnitInfo.Key
      }
    }
    return ($metricslist | Sort-Object -unique -property Group,Name,Rollup)
  }

  # Test if start is valid
  if($Start -ne $null -and $Start -ne &quot;&quot;){
    if($Start.gettype().name -ne &quot;DateTime&quot;) {
      Throw &quot;-Start parameter should be a DateTime value&quot;
    }
  }

  # Test if finish is valid
  if($Finish -ne $null -and $Finish -ne &quot;&quot;){
    if($Finish.gettype().name -ne &quot;DateTime&quot;) {
      Throw &quot;-Start parameter should be a DateTime value&quot;
    }
  }

  # Test start-finish interval
  if($Start -ne $null -and $Finish -ne $null -and $Start -ge $Finish){
    Throw &quot;-Start time should be 'older' than -Finish time.&quot;
  }

  # Test if stat is valid
  $unitarray = @()
  $InstancesList = @()

  foreach($st in $Stat){
    if($pcTable[$st] -eq $null){
      Throw &quot;-Stat parameter $st is invalid.&quot;
    }
    $pcInfo = $perfMgr.QueryPerfCounter($pcTable[$st])
    $unitarray += $pcInfo[0].UnitInfo.Key
    $metricId = $perfMgr.QueryAvailablePerfMetric($Entity.MoRef,$null,$null,$numinterval)

    # Test if QueryInstances in given
    if($QueryInstances){
      $mKey = $pcTable[$st]
      foreach($metric in $metricId){
        if($metric.CounterId -eq $mKey){
          $InstancesList += New-Object PSObject -Property @{
            Stat = $st
            Instance = $metric.Instance
          }
        }
      }
    }
    else{
      # Test if instance is valid
      $found = $false
      $validInstances = @()
      foreach($metric in $metricId){
        if($metric.CounterId -eq $pcTable[$st]){
          if($metric.Instance -eq &quot;&quot;) {$cInstance = '&quot;&quot;'} else {$cInstance = $metric.Instance}
          $validInstances += $cInstance
          if($Instance -eq $metric.Instance){$found = $true}
        }
      }
      if(!$found){
        Throw &quot;-Instance parameter invalid for requested stat: $st.`nValid values are: $validInstances&quot;
      }
    }
  }
  if($QueryInstances){
    return $InstancesList
  }

  $PQSpec = New-Object VMware.Vim.PerfQuerySpec
  $PQSpec.entity = $Entity.MoRef
  $PQSpec.Format = &quot;normal&quot;
  $PQSpec.IntervalId = $numinterval
  $PQSpec.MetricId = @()
  foreach($st in $Stat){
    $PMId = New-Object VMware.Vim.PerfMetricId
    $PMId.counterId = $pcTable[$st]
    if($Instance -ne $null){
      $PMId.instance = $Instance
    }
    $PQSpec.MetricId += $PMId
  }
  $PQSpec.StartTime = $Start
  $PQSpec.EndTime = $Finish
  if($MaxSamples -eq 0 -or $numinterval -eq 20){
    $PQSpec.maxSample = $null
  }
  else{
    $PQSpec.MaxSample = $MaxSamples
  }
  $Stats = $perfMgr.QueryPerf($PQSpec)

  # No data available
  if($Stats[0].Value -eq $null) {return $null}

  # Extract data to custom object and return as array
  $data = @()
  for($i = 0; $i -lt $Stats[0].SampleInfo.Count; $i ++ ){
    for($j = 0; $j -lt $Stat.Count; $j ++ ){
      $data += New-Object PSObject -Property @{
        CounterId = $Stats[0].Value[$j].Id.CounterId
        CounterName = $Stat[$j]
        Instance = $Stats[0].Value[$j].Id.Instance
        Timestamp = $Stats[0].SampleInfo[$i].Timestamp
        Interval = $Stats[0].SampleInfo[$i].Interval
        Value = $Stats[0].Value[$j].Value[$i]
        Unit = $unitarray[$j]
        Entity = $Entity.Name
        EntityId = $Entity.MoRef.ToString()
      }
    }
  }
  if($MaxSamples -eq 0){
    $data | Sort-Object -Property Timestamp -Descending
  }
  else{
    $data | Sort-Object -Property Timestamp -Descending | select -First $MaxSamples
  }
}</pre><p></p>
<h4>Annotations</h4>
<p><strong>Line 49</strong>: Determine the type of entity that was passed to the function</p>
<p><strong>Line 62-71</strong>: Create a hash table with all the available metrics and their metricId</p>
<p><strong>Line 79</strong>: Datastore statistics are only available from Historical Interval 2 (HI2) onwards.</p>
<p><strong>Line 82-103</strong>: Datastore metrics don&#8217;t seem to like the intervalId property. To avoid this problem, the script transforms the interval to a Start and Finish time, provided there were no explicit Start or Finish parameters passed.</p>
<p><strong>Line 94</strong>: For the Start time, the script substracts 1 interval duration from the length of the historical interval.</p>
<p><strong>Line 106-122</strong>: These lines handle the QueryMetrics switch</p>
<p><strong>Line 148-150</strong>: Test if a valid metric was passed on the Stat parameter</p>
<p><strong>Line 156-166</strong>: These lines handle the QueryInstances switch</p>
<p><strong>Line 167-181</strong>: Check if a valid Instance was passed</p>
<p><strong>Line 187-207</strong>: Construct the <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.PerformanceManager.QuerySpec.html" target="_blank">PerfQuerySpec</a> object</p>
<p><strong>Line 208</strong>: The actual call of the <a href="https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.PerformanceManager.html#queryStats" target="_blank">QueryPerf</a> method</p>
<p><strong>Line 230-235</strong>: Handle the presence of the MaxSamples parameter</p>
<h2>Sample runs</h2>
<p>Let&#8217;s start by investigating which metrics are available for a datastore.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">$ds = (Get-Datastore MyDS).Extensiondata
Get-Stat2 -entity $ds -interval &quot;HI2&quot; -QueryMetrics | ft -AutoSize</pre><p></p>
<p>The result of this call is a list with the available metrics.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/06/DS-stat4.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3324" title="DS-stat4" src="https://lucd.info/wp-content/uploads/2011/06/DS-stat4.png" alt="" width="374" height="77" srcset="https://www.lucd.info/wp-content/uploads/2011/06/DS-stat4.png 468w, https://www.lucd.info/wp-content/uploads/2011/06/DS-stat4-300x61.png 300w" sizes="auto, (max-width: 374px) 100vw, 374px" /></a></p>
<p>Next let&#8217;s see what instances are available.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Stat2 -entity $ds -interval &quot;HI2&quot; -stat &quot;disk.capacity.latest&quot; -QueryInstances</pre><p></p>
<p>As we already learned from the table above, this metric only has a &#8220;&#8221; instance.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/06/DS-stat5.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3325" title="DS-stat5" src="https://lucd.info/wp-content/uploads/2011/06/DS-stat5.png" alt="" width="484" height="47" srcset="https://www.lucd.info/wp-content/uploads/2011/06/DS-stat5.png 605w, https://www.lucd.info/wp-content/uploads/2011/06/DS-stat5-300x29.png 300w" sizes="auto, (max-width: 484px) 100vw, 484px" /></a></p>
<p>But the <strong>disk.used.latest</strong> metric has 3 different types of instances.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/06/DS-stat61.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3345" title="DS-stat6" src="https://lucd.info/wp-content/uploads/2011/06/DS-stat61.png" alt="" width="370" height="401" srcset="https://www.lucd.info/wp-content/uploads/2011/06/DS-stat61.png 462w, https://www.lucd.info/wp-content/uploads/2011/06/DS-stat61-276x300.png 276w" sizes="auto, (max-width: 370px) 100vw, 370px" /></a></p>
<p>Note that the VMid numbers that you see in this list do not necessarily mean that these virtual machines currently have files on the specific datastore. Remember that we are looking at historical data! The only way to know what is currently on the datastore, is to get the metrics and check if there are actual values returned for a specific VMid. If the value is <strong>-1</strong>, there were no files from that virtual machine on the datastore at that specific time.</p>
<p>Retrieving the actual statistical data is easy now.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">Get-Stat2 -entity $ds -stat &quot;disk.used.latest&quot; -interval &quot;HI2&quot; -Instance &quot;49364&quot; -MaxSamples 2</pre><p></p>
<p>As we expected, this gives us the statistical data for a specific virtual machine on the datastore.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/06/DS-stat7.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3330" title="DS-stat7" src="https://lucd.info/wp-content/uploads/2011/06/DS-stat7.png" alt="" width="290" height="192" srcset="https://www.lucd.info/wp-content/uploads/2011/06/DS-stat7.png 363w, https://www.lucd.info/wp-content/uploads/2011/06/DS-stat7-300x198.png 300w" sizes="auto, (max-width: 290px) 100vw, 290px" /></a></p>
<p>The original question, how to reproduce the specific graph that is available in the vSphere Client, becomes quite straightforward.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">$metrics = &quot;disk.capacity.latest&quot;,&quot;disk.provisioned.latest&quot;,
            &quot;disk.used.latest&quot;
$report = Get-Stat2 -entity $ds -stat $metrics -interval &quot;HI2&quot; | `
Sort-Object -Property Timestamp | `
Group-Object -Property Timestamp | %{
  New-Object PSObject -Property @{
    Timestamp = $_.Name
    &quot;Capacity (GB)&quot; = [Math]::Round(($_.Group | `
	    where {$_.CounterName -eq &quot;disk.capacity.latest&quot;}).Value/1MB,2)
    &quot;Allocated (GB)&quot; = [Math]::Round(($_.Group | `
	    where {$_.CounterName -eq &quot;disk.provisioned.latest&quot;}).Value/1MB,2)
    &quot;Used (GB)&quot; = [Math]::Round(($_.Group | `
	    where {$_.CounterName -eq &quot;disk.used.latest&quot;}).Value/1MB,2)
  }
}
$report | Export-Csv &quot;C:\DS-stats.csv&quot; -NoTypeInformation -UseCulture</pre><p></p>
<p>This produces a nice CSV file with the values from the graph.</p>
<p><a href="https://lucd.info/wp-content/uploads/2011/06/DS-stat91.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3337" title="DS-stat9" src="https://lucd.info/wp-content/uploads/2011/06/DS-stat91.png" alt="" width="495" height="344" srcset="https://www.lucd.info/wp-content/uploads/2011/06/DS-stat91.png 495w, https://www.lucd.info/wp-content/uploads/2011/06/DS-stat91-300x208.png 300w" sizes="auto, (max-width: 495px) 100vw, 495px" /></a></p>
<p>Notice how you can clearly see the addition of an 8 GB virtual disk, which we also saw in the screenshot at the top of this post.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2011/06/19/datastore-usage-statistics/feed/</wfw:commentRss>
			<slash:comments>32</slash:comments>
		
		
			</item>
	</channel>
</rss>
