How to generate a VSAN HTML Report with PowerCLI

 

Recently, I’ve been doing some catching up and reading about VSAN’s 6.2 latest features and I have to say that the deeper I dig, the greater my longing to get my hands dirty. Sadly, it won’t happen anytime soon. Currently I lack access to any real hardware on which to thoroughly test VSAN as one ought to. So, if there’s any vendor out there who’s feeling particularly altruistic, I wouldn’t mind having a few beefed up servers, SSDs and all, heading my way. Wishful thinking aside, I must content myself with using a virtualized setup which pretty much restricts me to exploring the most basic of features. For this post, I’ll be therefore using a 3-node nested 6.0 U2 cluster with emulated SSD disks. If you’d like to learn how to set it up, all the instructions are available in the How to setup VSAN on an ESXi Nested Environment post.

One thing leading to another, I somehow got side-tracked and ended up thinking on how PowerCLI can be used to retrieve VSAN related information. Better still how would I go about collating all the gathered info into a single HTML report, which is basically the topic for today’s post.

 

PowerCLI VSAN cmdlets


Using the command listed below, I searched for any PowerCLI cmdlets that might be VSAN related. I made the not-so-wild guess that any VSAN cmdlet would contain the string ‘VSAN’ in its name, which is in fact the case as per Figure 1. However, further research yielded another set of commands related to Storage Policy Based Management (SPBM) which can be used to extract details about – and even set – the VSAN storage policy.

For the record, I’m running PowerCLI 6.3 Release 1 which, to the best of my knowledge is the latest version at the time of writing this (Aug. ’16).

get-command -name *spbm*,*vsan*
Figure 1 - VSAN related PowerCLI cmdlets

Figure 1 – VSAN related PowerCLI cmdlets

I also learned, by trial and error, that the cluster object holds information about VSAN as shown marked in the next couple of screenshots (Figures 2 and 3).

Figure 2 - VSAN related properties from the cluster object

Figure 2 – VSAN related properties from the cluster object

Figure 3 - More VSAN related properties from the cluster object

Figure 3 – More VSAN related properties from the cluster object

 

After referencing the online PowerCLI cmdlet site and experimenting with some of the cmdlets, I started putting together a script, its aim being to retrieve basic VSAN-related data and present it on a single pane in the form of an HTML report.

I need to stress that this is no substitute to the functionality provided by the vSphere Web client or Ruby vSphere Console. However, I think that this is a good exercise, as it is illustrative, on how PowerCLI and PowerShell can be used to provide practical solutions to many problems we come across on a daily basis in vSphere land.

From the vSphere Web Client, you can monitor both the VSAN’s health as well as retrieve information on the pooled physical disks making up the VSAN datastore. The script mostly emulates what’s shown in Figure 4 and 5. In addition, I included the queue depth which I can’t find listed anywhere when using the vSphere Web client.

Figure 4 - vSphere Web Client - VSAN Physical disk information

Figure 4 – vSphere Web Client – VSAN Physical disk information

To view all the disk related info in vSphere Web Client, change the view to Datastore and select the vsanDatastore datastore.  As per Figure 5, select the Manage tab followed by the Settings tab. Next, choose Device Backing and click on Disks. Right-click on the table header, select Show/Hide Columns … and click on Select All and the OK button to expose all the disk details.

Figure 5 - vSphere Web Client - Device Backing details

Figure 5 – vSphere Web Client – Device Backing details

Figure 6 -  vSphere Web Client - VSAN Health monitoring

Figure 6 –  vSphere Web Client – VSAN Health monitoring

 

The Script


I’ve made a few assumptions to keep the script as simple as possible, one of which is that it will be run against environments where only one cluster exists. The cluster name is specified in the Declarations section using var $clusName.  I’m also assuming that the default vSAN storage policy is being used. This is specified by $vSANPolName. Lastly, note that any established vCenter or ESXi connections will be dropped by the script when executed.

As a side-note, I decided to embed HTML tags and code while building the report instead of using something like convertto-html. This method, in my opinion, allows further flexibility as far as content layout is concerned.

All the VSAN related information used to build the report is obtained via the following lines of code;

$Clus = Get-Cluster -Name $ClusName
$vSanDisks = Get-VSanDisk
$vSanDGroups = Get-VsanDiskGroup
$vSANPolicy = (Get-SpbmStoragePolicy -Name $vSANPolName).AnyOfRuleSets.allofrules
$vSANDS = (Get-Datastore -Name $vSANDSName)

One nifty trick you should know about – unless you already do – is the here-string which allows you to type in multi-lined formatted strings without the need to concatenate or wrap special characters. The only thing you need to remember is to enclose the string using @” at the start and “@ at the end. The closing “@ must reside on a separate line with no preceding characters or spaces. You can also embed variables within the string itself. However, note that when computing variables on the fly, that is variables initialized within the here-string block and not outside its scope, the format $($var) must be used. Here’s an example showing a previously initialized var;

$health=(@"
 <br>
   <font color=#2F2F2F><h3>Health</h3></font>
 <table>
     <tr>
      <th>Issues</th>
     </tr>
     <tr>
      <td>$vSANIssues</td>
   </tr>
 </table>
"@)

The script is reproduced in its entirety at the end of the post. Before moving on, however, have a look at Fig.7 which shows a screenshot of the final report generated by the script. The report is divided into 5 parts.

The first, General Info, gives a quick overview which includes whether VSAN is enabled or not, the number of disk groups and disks used and the disk claim mode (manual or automatic). The second part, Health, provides a somewhat bleak overview on the VSAN health status. So far, I haven’t found the means to retrieve the health information returned by the vSphere Web Client other than the FullFormattedMessage property for the cluster object. I am aware that the VSAN 6.2 API includes new managed objects but as things stands it seems that these cannot be consumed from PowerCLI. If anyone knows otherwise, by all means drop me a line down below.

The third section summarizes the disk details found in the vSAN datastore, flash or otherwise. The fourth section provides information about the vSAN datastore while the fifth and final section lists the values specified in the rulesets within the default vSAN storage policy (see Fig.8).

Figure 7 - HTML report generated by the script

Figure 7 – HTML report generated by the script

I’ve test run the script both from the PowerCLI command window and PowerGUI, which is an IDE I generally use. It’s best to copy the code using the copy function from the top-right corner of the code window below rather than straight off this page. For anyone who’s interested, I also have a slightly modified version of the script that outputs to XML instead.

Note: The disk format values returned by PowerCLI seem to differ from those reported in vSphere Client. Specifically, the ExtensionData.VsanDiskInfo.FormatVersion property is set to 4 when queried in PowerCLI whereas the Web vSphere client reports a value of  3. Not sure if this is a bug or something gone wrong with my environment.

Figure 8 - Rules-set values for the default vSAN storage policy

Figure 8 – Ruleset values for the default vSAN storage policy

 

I hope you’ll find the script useful and as always, feel free to drop me a comment or question and I’ll be glad to reply back to the best of my abilities.

# A PowerCLI script that retrieves VSAN related info and outputs it in HTML format.
# Jason Fenech (Aug 16)
#----------------------------------------------------------[Libraries]-----------------------------------------------
# Uncomment the 2 lines below if running script using PowerShell (not PowerCLI)
#
# Import-Module VMware.VimAutomation.Core -ErrorAction SilentlyContinue
# Import-Module VMware.VimAutomation.Storage -ErrorAction SilentlyContinue
#----------------------------------------------------------[Declarations]--------------------------------------------
#Change the following as required
####################################################################################
 $vSANFile = "C:\test\vsan.html"                   #Path to generated report
 $vCenter="vcenter-name"                           #vCenter hostname or IP Address
 $clusName = "cluster-name"                        #Cluster name
 $user="user"                                      #vCenter Server user
 $pass="password"                                  #vCenter Server user's password
 $vSANPolName="Virtual SAN Default Storage Policy" #vSAN Storage Policy - Assuming default name
 $vSANDSName="vsanDatastore"                       #Default name for the VSAN DS
####################################################################################

 $vSANIssues=""                                    #Holds VSAN error / warning msg
 $dn=0                                             #Disk counter

#Style applied to tables
$style = @"
 table {
 font-family: arial, sans-serif;
 border-collapse: collapse;
 }
  td, th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
  font-size: 14px;
 }
  tr:nth-child(1) {
  background-color: #ddcccc;
}
"@
#----------------------------------------------------------[Execution]-----------------------------------------------
#Drop any existing open VI connections and connect to vCenter Server $vCenter
try{
    Disconnect-VIServer * -force -Confirm:$false -ErrorAction SilentlyContinue
    Connect-VIServer -Server $vCenter -User $user -Password $pass -ErrorAction Stop
}
catch{
    Write-Host "Failed to connect to vCenter Server $vCenter"
    exit                                           #Exit script on error
}

#Retrieve cluster and vSAN info
 $Clus = Get-Cluster -Name $ClusName
 $vSanDisks = Get-VSanDisk
 $vSanDGroups = Get-VsanDiskGroup
 $vSANPolicy = (Get-SpbmStoragePolicy -Name $vSANPolName).AnyOfRuleSets.allofrules
 $vSANDS = (Get-Datastore -Name $vSANDSName)

#Write HTML doc header
(@"
 <!DOCTYPE html>
 <head>
  <title>VSAN Report</title>
  <style>$style</style>
 </head>
  <body>
   <h2>VSAN Report - Cluster $ClusName</h2><hr>
"@) | Out-File $vSANFile -Append

#--------------------------------------------------------------------------------------------------------------------
#Write vSAN General Info Table Header and Data
(@"
 <br>
 <font color=#2F2F2F><h3>General Info</h3></font>
 <table>
  <tr>
   <th>VSAN enabled?</th>
   <th>Disk Groups</th>
   <th>SSD Disks</th>
   <th>Non-SSD Disks</th>
   <th>Disk Claim Mode</th>
  </tr>
  <tr>
   <td>$($clus.VsanEnabled)</td>
   <td>$(($vSanDGroups).count)</td>
   <td>$(($vSanDisks | where {$_.IsSSD -eq "True"}).count)</td>
   <td>$(($vSanDisks | where {$_.IsSSD -ne "True"}).count)</td>
   <td>$($clus.VsanDiskClaimMode)</td>
  </tr>
 </table>
"@) | Out-File $vSANFile -Append

#--------------------------------------------------------------------------------------------------------------------
#Check if there are any issues related to the VSAN config
if ($Clus.ExtensionData.ConfigIssue.ObjectName -eq "VSAN")
    {$vSANIssues = $Clus.ExtensionData.ConfigIssue[0].FullFormattedMessage}

#vSAN Health Table Header and Data
(@"
 <br>
 <font color=#2F2F2F><h3>Health</h3></font>
  <table>
   <tr>
    <th>Issues</th>
   </tr>
   <tr>
    <td>$vSANIssues</td>
   </tr>
  </table>
"@) | Out-File $vSANFile -Append

#--------------------------------------------------------------------------------------------------------------------
#vSAN Disks Info Table Header and Data
 (@"
 <br>
 <font color=#2F2F2F><h3>Disks</h3></font>
  <table>
   <tr>
    <th>Disk #</th>
    <th>Name</th>
    <th>Health</th>
    <th>Vendor</th>
    <th>Model</th>
    <th>SSD</th>
    <th>Size (GB)</th>
    <th>Queue Depth</th>
    <th>Format Ver.</th>
    <th>vSAN UIID</th>
    <th>ESXi Host</th>
    <th>Disk Group</th>
   </tr>
"@) | Out-File $vSANFile -Append

#Return data for every vSAN disk found
 $vSanDisks | % {
     $diskSize = ($_.ExtensionData.Capacity.BlockSize * $_.ExtensionData.Capacity.Block) / (1024*1024*1024);
 
 $health = $_.ExtensionData.OperationalState
  if ($health -eq "ok") {$health="<font color=""green""><b>Healthy</b></font>"}
    else {$health="<font color=""red""><b>Check Disk</b></font>"}
(@"
  <tr>
   <td>$dn</td>
   <td>$($_.Name)</td>
   <td>$health</td>
   <td>$($_.ExtensionData.Vendor)</td>
   <td>$($_.ExtensionData.Model)</td>
   <td>$($_.IsSsd)</td>
   <td>$diskSize</td>
   <td>$($_.ExtensionData.QueueDepth)</td>
   <td>$($_.ExtensionData.VsanDiskInfo.FormatVersion)</td>
   <td>$($_.ExtensionData.VsanDiskInfo.VsanUuid)</td>
   <td>$($_.VsanDiskGroup.vmhost.name)</td>
   <td>$($_.VsanDiskGroup)</td>
  </tr>
"@) | Out-File $vSANFile -Append
 
 #Disk counter
  $dn++
}

#--------------------------------------------------------------------------------------------------------------------
#vSAN Datastore Table Header and Data

(@"
 </table>
 <br>
  <font color=#2F2F2F><h3>vSAN Datastore Details</h3></font>
  <table>
   <tr>
    <th>State</th>
    <th>Capacity (GB)</th>
    <th>Free Space (GB)</th>
    <th>ID</th>
   </tr>
   <tr>
    <td>$($vSANDS.State)</td>
    <td>$($vSANDS.CapacityGB)</td>
    <td>$($vSANDS.FreeSpaceGB)</td>
    <td>$($vSANDS.Id)</td>
   </tr> 
 </table>
"@) | Out-File $vSANFile -Append

#--------------------------------------------------------------------------------------------------------------------
#vSAN Storage Policy Table Header and Data

(@"
 </table>
  <br>
  <font color=#2F2F2F><h3>vSAN Storage Policy</h3></font>
 <table>
 <tr>
"@) | Out-File $vSANFile -Append

#Get rules set capabilities
 $vSANPolicy | % {                                    
 (@"
  <th>
   $($_.Capability)
  </th>
"@) | Out-File $vSANFile -Append
}

#Close current row and start a new one
 "</tr><tr>" | Out-File $vSANFile -Append 

#Get rules set capabilities values
 $vSANPolicy | % { 
 (@"
  <td>
   $($_.value)
  </td>
"@) | Out-File $vSANFile -Append
}

#--------------------------------------------------------------------------------------------------------------------
#Write file tail
$(@"
 </tr>
 </table>
 </body>
 </html>
"@) | Out-File $vSANFile -Append
Altaro VM Backup
Share this post

Not a DOJO Member yet?

Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!

9 thoughts on "How to generate a VSAN HTML Report with PowerCLI"

  • Vijay says:

    Thanks for your script. Let me know, how to use for multiple clusters in vSAN and also am trying to do dashboard about vSAN cluster health check.

    • Jason Fenech says:

      Hi. Thanks for the feedback first of all. Unfortunately, I don’t have the time to revisit the script at this time. That said, it should be fairly easy to factor in for multiple clusters. Plenty of code out there.

Leave a comment

Your email address will not be published.