Storage Views – Datastores

In the vCenter Client, since vSphere 4, you can find a Storage Views tab on several of the VI containers. The data in these Storage Views is collected and provided by the vCenter Storage Monitoring plug-in.

Have a look at David Davis‘s post, called Using VMware vSphere Storage Views, for more information on what you can do with the Storage Views.

Some time ago I got a question from Andrew how the Multipathing Status 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.

The primary reason I created this function, is that it will allow to schedule the creation of the Storage Views – Datastores values at regular intervals. A feature that is unfortunately missing from the vCenter Client plug-in.

With those saved values it is easy to produce reports that show who is consuming the storage over time.

The script

Annotations

Line 29-40: The function uses 5 parameter sets that allow you to get the Storage Views – Datastores values for a VM, an ESX(i) server, a ResourcePool, a Cluster or a Datacenter.

Line 44-85: 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.

Line 88-89: 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.

Line 92-95: 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.

Line 98-171: The main loop over all the datastores that the script needs to handle.

Line 101-102: The script collects all the LUNs that are part of the datastore.

Line 103: The Multipathing logic works with a copy of the hash table that was created earlier.

Line 106-108: In the hash table the script increments the value for each LUN path that is Active or Standby.

Line 109-114: If a LUN has more then 1 path, the Multipathing Status is considered as Full Redundancy. Otherwise the status is Partial/No Redundancy.

Line 118-153: The script calculates all values that are related to the storage in use by the VMs.

Line 125: 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.

Line 127: 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.

Line 128: The Space Used value is the sum of all the Committed space for each of the VMs on that datastore.

Line 129-135: The space used by snapshots is the sum of all the VMDK snapshot files and the snapshotList and the snapshotData files.

Line 132: 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.

Line 136-139: All the files used for the vDisks of a VM.

Line 140-143: All swap related files

Line 144-147: All other files that are used by the VM.

Line 148-151: 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 VirtualMachineRelocateSpec).

Line 156-170: 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 Get-FriendlyUnits function from my Friendly Units post.

Line 166: Note that for the Virtual Disk Space value we need to subtract the Snapshot Space from the total disk space.

Samples

You can pass the function the name of the object for which you want the Storage Views – Datastore values.

Or you can pass the actual object.

The previous example also showed how the results can be saved to a CSV file.
Such a CSV file looks as follows.

Enjoy the function !

10 Comments

    Kiran

    Taking long time tho.. thanks for sharing

    Brad S

    Great script any way to increase the performance? Running it seems to take forever =)

    Islander

    LucD,

    I am still lost, I do not understand how to run this script, if you can explained one more time to me, I copied and saved the script as a getstorage-view.PS1 executed and does not do anything.

    I’ve looking for a a script that tells me what are the status of my SAN, my SAN currently is overflowing, because file overallocation, I would like to know how may I approach this problem. I found two scripts that are closed to what I am looking for, if may be there is a way to incorporate some values that will do the trick, here are the two:

    Here are the line of code that I would like to incorporate:

    get-vm |sort | % {$_.name ; ($_|get-harddisk | % {$_.filename;$_.capacitykb})}

    That is driving me crazy, again the main problem is that many of my LUN’s are running out of space, but if could identify, the VMDK’s or Template files, where and what are they, I should be able to find a solution.

    First Script:

    Import-Module VIProperty

    $users = “user@xyz.xyz” # List of users to email your report to (separate by comma)
    $fromemail = “user@xyz.xyz”
    $server = “smtp.server.xyz” #enter your own SMTP server DNS name / IP address here

    $datastore = $null
    $Report = @()
    $AllDatastores = Get-Datastore | Where {$_.Name -notlike “datastore*”} | Sort Name
    foreach ($datastore in $AllDatastores) {
    $Report += “”
    $row = “” | Select Name, FreeGB, CapacityGB, ProvisionedGB, PercentFree
    $row.Name = $datastore.Name
    $row.FreeGB = $datastore.FreeGB
    $row.CapacityGB = $datastore.CapacityGB
    $row.ProvisionedGB = $datastore.ProvisionedGB
    $row.PercentFree = $datastore.PercentFree
    $Report += $row | ConvertTo-Html

    #List VMs on the datastore if applicable
    If ($datastore.ExtensionData.Vm.Count -gt 0){
    $VMList = Get-View -Id $datastore.ExtensionData.Vm -Property Name | Select Name
    $Report += “”
    $Report += “VMs on this Datastore:
    $VMTable = @()
    foreach ($vm in $VMList) {
    $VMContentRow = “” | Select Name, PowerState
    $tmp = Get-VM $vm.Name
    $VMContentRow.Name = $tmp.Name

    Write-Host $tmp.Name
    if ($tmp.PowerState -eq “PoweredOn”) {
    $VMContentRow.PowerState = $tmp.PowerState
    }
    else {
    $VMContentRow.PowerState = $tmp.PowerState
    }

    $VMTable += $VMContentRow

    }

    $Report += $VMTable | ConvertTo-Html -Fragment

    }
    else {
    $Report += “”
    $Report += “VMs on this Datastore:
    $Report += “Name”
    $Report += “No VMs on this Datastore”

    }

    $Report += “” #Line break for clarity
    $Report += “”
    }

    # HTML formatting for email
    $HTMLmessage = @”

    Datastore Report

    body{font: .8em “”Lucida Grande””, Tahoma, Arial, Helvetica, sans-serif;}
    ol{margin:0;padding: 0 1.5em;}
    TABLE{border-width: 1px;border-style: solid;border-color: black;}
    TH{border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
    TD{text-align:center;border-width: 1px;padding: 5px;border-style: solid;border-color: black;}
    table{color:#000;background:#99CCFF;border-collapse:collapse;width:647px;border:3px solid #900;}
    thead{}
    thead th{padding:1em 1em .5em;border-bottom:1px dotted #FFF;font-size:120%;text-align:left;}
    thead tr{}
    td{padding:.5em 1em;}
    tfoot{}
    tfoot td{padding-bottom:1.5em;}
    tfoot tr{}
    #middle{background-color:#900;}

    $Report

    “@

    $HTMLmessage | Out-File C:\DSReport.html #Also write to an HTML report on disk – with basic formatting, in addition to the email report you are sent.

    #Send the final report!
    send-mailmessage -from $fromemail -to $users -subject “Datastore Report” -BodyAsHTML -body $HTMLmessage -smtpServer $server

    NOTE: here is the line of code that I am struggling with, I do not know where to place it:

    get-vm |sort | % {$_.name ; ($_|get-harddisk | % {$_.filename;$_.capacitykb})}

    Here is a second script, it does the same as the first one, but this one has less lines with pretty much the same approach:

    Script 2:

    Import-Module VIProperty

    $users = “yourmail@yourdomain.com” # List of users to email your report to (separate by comma)
    $fromemail = “yourmail@yourdomain.com”
    $server = “yourmailserver.com” #enter your own SMTP server DNS name / IP address here

    $Report = @()
    ## done to exclude local datastores?
    $AllDatastores = Get-Datastore | Where {$_.Name -notlike “datastore*”} | Sort Name
    foreach ($datastore in $AllDatastores) {
    $Report += “”
    $row = New-Object -Type PSObject -Property @{
    Name = $datastore.Name
    FreeGB = $datastore.FreeGB
    CapacityGB = $datastore.CapacityGB
    PercentFree = $datastore.PercentFree
    } ## end new-object
    $Report += $row | ConvertTo-Html

    #List VMs on the datastore if applicable
    $Report += “”
    $Report += “VMs/Templates on this Datastore:
    if ($datastore.ExtensionData.Vm.Count -gt 0){
    $VMViewList = Get-View -Id $datastore.ExtensionData.Vm -Property Name,Runtime.PowerState,Config.Template
    $VMTable = @()
    foreach ($viewVM in $VMViewList) {
    Write-Host $viewVM.Name
    $VMContentRow = New-Object -Type PSObject -Property @{
    Name = $viewVM.Name
    PowerState = $viewVM.Runtime.PowerState
    Other = if ($viewVM.Config.Template) {“Template”} else {“VM”}
    } ## end new-object
    $VMTable += $VMContentRow
    }
    $Report += $VMTable | ConvertTo-Html -Fragment
    } ## end if
    else {
    $Report += ‘None on this Datastore’
    } ## end else

    $Report += “” #Line break for clarity
    $Report += “”
    } ## end foreach

    $Report | Set-Content C:\DSReport.html #Also write to an HTML report on disk – with basic formatting, in addition to the email report you are sent.

    Again, I would like to incorporate this line of code into the script:

    get-vm |sort | % {$_.name ; ($_|get-harddisk | % {$_.filename;$_.capacitykb})}

    Any assistance would be greatly appreciated.

    Thanks,

    Rue

    By specifying the HBA type as “Fiberchannel’ won’t this give an incorrect multipath status for iscsi connections ?

    Jen

    Hi, I am not sure where to post this question, I hope this is ok 😉 …

    I am trying to take datastore information, including the datacenter name, and export it to SQLServer. I am using both functions out-datatable and write-datatable which Marc van Orsouw has posted and someone else has modified (https://blogs.technet.com/b/heyscriptingguy/archive/2010/11/01/use-powershell-to-collect-server-data-and-write-to-sql.aspx).

    I am getting all datastores and putting them in to an array with the datacenter name. However, the datacenter name has a hyphen (datacenter-xx). This will not write to sql because it is not in quotes I am told by my db admin. I have not been able to figure out how to get around this, would you help? Thanks!

      LucD

      Hi Jen, no problem.
      I suppose your question is answered in the Remove the hyphen of the datacenter name for export purposes thread on the PowerCLI Community.

    Sallu

    This may be a stupid question but not sure how to run this script, its very important for me to make this script working.
    can somebody tell me how do I run this script, and in which part of the script do I need to supply the values!!

      LucD

      @Sallu, there are no stupid questions 😉
      The script is written as a function. In this function there are 5 parameter sets, each with 1 parameter, the vSphere object for which you want to generate the Storage View. That vSphere object can be an ESX(i) host, a Datacenter, a Cluster, a ResourcePool or a VM.
      In the Samples section there are a couple of sample calls.

      But you need to make the function ‘known’ to the PowerShell engine.

      • Save the function as .PS1 file, for example ‘DSView.ps1’
      • I assume you are running the PowerCLI prompt
      • at the prompttype, note the blank between the 2 dots !
        . ./DSView.ps1
      • Call the function with the parameter, in this case the name of a Datacenter
        Get-StorageViewDatastore -Datacenter MyDatacenter
      • The function returns a numnber of objects, extract the information (properties) you require from these objects.
      • See the example Select-Object cmdlet in the Samples section

      I hope this helped you in running the function.

    bs

    great job!

    Marcel Nobel

    Another great script. Bedankt!

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.