My Daily Hyper-V Status Email–Part 4 of 5

Now that I have talked about displaying event log information and virtual machine health information; the next part of my status email is storage health information.

In my experience – the most common failure for my servers is a failed hard disk.  Now, as I have multiple levels of redundancy configured in my storage configuration, it is not always obvious that a disk has failed.  Luckily, it is very easy to get this information with PowerShell.

image

In fact, this is one of the primary reasons why I like using storage spaces.  The great integration with PowerShell.  Here is the code that I use to generate this table:

 # Storage Health
 $message = $message + "<style>TH{background-color:DarkGreen}TR{background-color:$($errorColor)}</style>"
 $message = $message + "<B>Storage Health</B> <br> <br>"
 $message = $message + "Physical Disk Health: <br>" + ((Get-PhysicalDisk | `
                                                            Select-Object @{Expression={$_.FriendlyName};Label="Physical Disk Name"},  `
                                                                          @{Expression={$_.DeviceID};Label="Device ID"}, `
                                                                          @{Expression={$_.OperationalStatus};Label="Operational Status"}, `
                                                                          @{Expression={$_.HealthStatus};Label="Health Status"}, `
                                                                          @{Expression={"{0:N2}" -f ($_.Size / 1073741824)};Label="Size (GB)"} `
                                                                          | ConvertTo-HTML -Fragment) `
                                                                          | %{if($_.Contains("<td>OK</td><td>Healthy</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
                                                                          + " <br>"
 $message = $message + "Storage Pool Health: <br>" + ((Get-StoragePool | `
                                                       where-object {($_.FriendlyName -ne "Primordial")} | `
                                                           Select-Object @{Expression={$_.FriendlyName};Label="Storage Pool Name"}, `
                                                                         @{Expression={$_.OperationalStatus};Label="Operational Status"}, `
                                                                         @{Expression={$_.HealthStatus};Label="Health Status"} `
                                                                         | ConvertTo-HTML -Fragment) `
                                                                         | %{if($_.Contains("<td>OK</td><td>Healthy</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
                                                                         + " <br>"
 $message = $message + "Virtual Disk Health: <br>" + ((Get-VirtualDisk | `
                                                           Select-Object @{Expression={$_.FriendlyName};Label="Virtual Disk Name"}, `
                                                                         @{Expression={$_.OperationalStatus};Label="Operational Status"}, `
                                                                         @{Expression={$_.HealthStatus};Label="Health Status"} `
                                                                         | ConvertTo-HTML -Fragment) `
                                                                         | %{if($_.Contains("<td>OK</td><td>Healthy</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
                                                                         + " <br>"

Notes about this code:

  • I am using “Get-PhysicalDisk”, “Get-StoragePool” and “Get-VirtualDisk” to gather the raw data.
  • Once again - I use raw HTML to set the color of the table headers. 
  • Again - I run the output of these commands through Select-Object with the use of the “Expression” option to set column labels appropriately.
  • Again - I use ConvertTo-HTML –Fragment to get a nice HTML table outputted.
  • Again – I implement color coding for individual entries in the table.  I set each table cell to be “red” by default.  I then do some string parsing to see if the health is good – and switch the background color if I get a positive result.

Cheers,

Ben