mirror of
https://github.com/tsmagnum/Hyper-V-Report.git
synced 2026-04-17 15:43:26 +02:00
343 lines
9.7 KiB
PowerShell
343 lines
9.7 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Generates a comprehensive HTML report of the Hyper-V environment, including host details,
|
|
virtual machines, snapshots, replication status, VHDX files, network adapters,
|
|
and virtual switches. Optionally sends the report via email.
|
|
|
|
.DESCRIPTION
|
|
The Hyper-V-Report.ps1 script is designed to automate the collection and reporting of key metrics
|
|
and configuration details from a Hyper-V infrastructure. It supports both standalone and
|
|
(future) clustered deployments and provides detailed insights into:
|
|
|
|
Host system resources and configuration
|
|
Virtual machine specifications and states
|
|
Snapshot inventory and age
|
|
Replication status and health
|
|
VHDX file properties and fragmentation
|
|
VM and management OS network adapter configurations
|
|
Virtual switch topology and uplinks
|
|
|
|
The script generates an HTML report and can send it via email using either MS Graph or MailKit,
|
|
depending on the configuration.
|
|
It relies on external modular scripts (GlobalVariables.ps1, StyleCSS.ps1, HtmlCode.ps1, Functions.ps1)
|
|
for customization and formatting.
|
|
|
|
.EXAMPLE
|
|
.\Hyper-V-Report.ps1
|
|
#>
|
|
|
|
#Region Credits
|
|
#Author: Federico Lillacci
|
|
#Github: https://github.com/tsmagnum
|
|
#endregion
|
|
|
|
# Setup all paths required for script to run
|
|
|
|
#Scripted execution
|
|
$ScriptPath = (Split-Path ((Get-Variable MyInvocation).Value).MyCommand.Path)
|
|
|
|
#Getting date (logging,timestamps, etc.)
|
|
$today = Get-Date
|
|
$launchTime = $today.ToString('ddMMyyyy-hhmm')
|
|
|
|
#Importing required assets
|
|
. ("$($ScriptPath)\GlobalVariables.ps1")
|
|
. ("$($ScriptPath)\HtmlCode.ps1")
|
|
. ("$($ScriptPath)\Functions.ps1")
|
|
|
|
#Setting the report style
|
|
switch ($reportStyle) {
|
|
minimal
|
|
{ $styleSheet = "StyleCSS-Minimal.ps1" }
|
|
pro
|
|
{ $styleSheet = "StyleCSS-Pro.ps1" }
|
|
prodark
|
|
{ $styleSheet = "StyleCSS-ProDark.ps1" }
|
|
colorful
|
|
{ $styleSheet = "StyleCSS-Colorful.ps1" }
|
|
Default
|
|
{ $styleSheet = "StyleCSS-Professional.ps1" }
|
|
}
|
|
|
|
. ("$($ScriptPath)\Style\$styleSheet")
|
|
|
|
#Setting the report filename
|
|
$reportHtmlFile = $reportHtmlDir+"\$($reportHtmlName)_"+$launchTime+".html"
|
|
|
|
#Setting the encrypted creds file path
|
|
if ($emailReport)
|
|
{
|
|
$encryptedSMTPCredsFile = "$($ScriptPath)\$encryptedSMTPCredsFileName"
|
|
}
|
|
|
|
#Region Hosts
|
|
$vmHosts = [System.Collections.ArrayList]@()
|
|
|
|
#Getting Host infos
|
|
if ($clusterDeployment)
|
|
{
|
|
$clusterNodes = Get-ClusterNode -Cluster .
|
|
|
|
foreach ($clusterNode in $clusterNodes)
|
|
{
|
|
$vmHost = Get-VMHost -ComputerName $clusterNode.NodeName
|
|
|
|
[void]$vmHosts.Add($vmHost)
|
|
}
|
|
|
|
$vmHostsList = Get-VmHostInfo -vmHosts $vmHosts
|
|
}
|
|
|
|
#Non clustered deployments
|
|
else
|
|
{
|
|
$vmHost = Get-VMHost
|
|
|
|
$vmHostsList = Get-VmHostInfo -vmHosts $vmHost
|
|
}
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Hyper-V Hosts infos ######"
|
|
$vmHostsList | Format-Table
|
|
|
|
#endregion
|
|
|
|
#Region CSV Health - Only for clustered environments
|
|
if (($clusterDeployment) -and ($csvHealthInfoNeeded))
|
|
{
|
|
$csvHealthList = Get-CsvHealth -clusterNodes $clusterNodes
|
|
|
|
Write-Host -ForegroundColor Cyan "###### CSV Health Info ######"
|
|
$csvHealthList | Format-Table
|
|
}
|
|
#endregion
|
|
|
|
#Region CSV Space Utilization - Only for clustered environments
|
|
if ($clusterDeployment)
|
|
{
|
|
$csvSpaceList = Get-CsvSpaceUtilization
|
|
|
|
Write-Host -ForegroundColor Cyan "###### CSV Space Utilization ######"
|
|
$csvSpaceList | Format-Table
|
|
}
|
|
#endregion
|
|
|
|
#Region VMs
|
|
#Getting VMs detailed infos
|
|
$vmsList =@()
|
|
|
|
if ($clusterDeployment)
|
|
{
|
|
$vms = foreach ($clusterNode in $clusterNodes)
|
|
{
|
|
Get-VM -ComputerName $clusterNode.NodeName
|
|
}
|
|
}
|
|
|
|
#Non clustered deployments
|
|
else
|
|
{
|
|
$vms = Get-VM
|
|
}
|
|
|
|
foreach ($vm in $vms)
|
|
{
|
|
$vmInfo = Get-VmInfo -vm $vm
|
|
|
|
$vmsList += $vmInfo
|
|
}
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Virtual Machines infos ######"
|
|
$vmsList | Format-Table
|
|
|
|
#endregion
|
|
|
|
#Region Snapshots
|
|
#Getting Snapshots
|
|
$vmSnapshotsList = Get-SnapshotInfo -vms $vms
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Snapshots infos ######"
|
|
$vmSnapshotsList | Format-Table
|
|
#endregion
|
|
|
|
#Region replication
|
|
if($replicationInfoNeeded)
|
|
{
|
|
$replicationsList = Get-ReplicationInfo -vms $vms
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Replication infos ######"
|
|
$replicationsList | Format-Table
|
|
|
|
}
|
|
#endregion
|
|
|
|
#Region VHDX
|
|
if ($vhdxInfoNeeded)
|
|
{
|
|
$vhdxList = Get-VHDXInfo -vms $vms
|
|
|
|
Write-Host -ForegroundColor Cyan "###### VHDX infos ######"
|
|
$vhdxList | Format-Table
|
|
}
|
|
#endregion
|
|
|
|
#Region VMNetworkAdapter
|
|
if ($vmnetInfoNeeded)
|
|
{
|
|
$vmnetAdapterList = Get-VmnetInfo -vms $vms
|
|
|
|
Write-Host -ForegroundColor Cyan "###### VM Net Adapters infos ######"
|
|
$vmnetAdapterList | Format-Table
|
|
|
|
}
|
|
#endregion
|
|
|
|
#Region Management OS NetworkAdapter
|
|
if ($osNetInfoNeeded)
|
|
{
|
|
if ($clusterDeployment)
|
|
{
|
|
$osNetAdapterList = Get-OsNetAdapterInfo -vmHost $vmHosts
|
|
}
|
|
|
|
else
|
|
{
|
|
$osNetAdapterList = Get-OsNetAdapterInfo -vmHost $vmHost
|
|
}
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Management OS Adapters infos ######"
|
|
$osNetAdapterList | Format-Table
|
|
|
|
}
|
|
#endregion
|
|
|
|
#Region VirtualSwitch
|
|
if ($vswitchInfoNeeded)
|
|
{
|
|
|
|
if ($clusterDeployment)
|
|
{
|
|
$vswitchesList = Get-VswitchInfo -vmHost $vmhosts
|
|
}
|
|
|
|
else
|
|
{
|
|
$vswitchesList = Get-VswitchInfo -vmHost $vmhost
|
|
}
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Virtual Switches infos ######"
|
|
$vswitchesList | Format-Table
|
|
}
|
|
#endregion
|
|
|
|
#Region Cluster Configuration Info
|
|
if ($clusterDeployment -and $clusterConfigInfoNeeded)
|
|
{
|
|
$clusterConfigInfoList = Get-ClusterConfigInfo
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Cluster config infos ######"
|
|
$clusterConfigInfoList | Format-Table
|
|
}
|
|
#endregion
|
|
|
|
#Region Cluster Networks Info
|
|
if ($clusterDeployment -and $clusterNetworksInfoNeeded)
|
|
{
|
|
$clusterNetworksList = Get-ClusterNetworksInfo
|
|
|
|
Write-Host -ForegroundColor Cyan "###### Cluster networks infos ######"
|
|
$clusterNetworksList | Format-Table
|
|
}
|
|
#endregion
|
|
|
|
############### Report and Email ###############
|
|
|
|
#Creating the HTML report
|
|
if ($reportHtmlRequired)
|
|
{
|
|
$dataHTML = [System.Collections.ArrayList]@()
|
|
|
|
$vmhostsHTML = $preContent + $titleHtmlHosts + ($vmHostsList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($vmhostsHTML)
|
|
|
|
if (($clusterDeployment) -and ($csvHealthInfoNeeded))
|
|
{
|
|
$csvHealthHTML = $titleHtmlcsvHealth + ($csvHealthList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($csvHealthHTML)
|
|
}
|
|
|
|
if ($clusterDeployment)
|
|
{
|
|
$csvSpaceHTML = $titleHtmlcsvSpace + ($csvSpaceList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($csvSpaceHTML)
|
|
}
|
|
|
|
$vmsHTML = $titleHtmlVms + ($vmsList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($vmsHTML)
|
|
|
|
$snapshotsHTML = $titleHtmlSnapshots + ($vmSnapshotsList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($snapshotsHTML)
|
|
|
|
if ($replicationInfoNeeded)
|
|
{
|
|
$replicationHTML = $titleHtmlReplication + ($replicationsList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($replicationHTML)
|
|
}
|
|
|
|
if ($vhdxList)
|
|
{
|
|
$vhdxListHTML = $titleHtmlVhdx + ($vhdxList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($vhdxListHTML)
|
|
}
|
|
|
|
if ($vmnetInfoNeeded)
|
|
{
|
|
$vmnetAdapterListHTML = $titleHtmlVmnetAdapter + ($vmnetAdapterList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($vmnetAdapterListHTML)
|
|
}
|
|
|
|
if ($osNetInfoNeeded)
|
|
{
|
|
$osNetAdapterListHTML = $titleHtmlOsNetAdapter + ($osNetAdapterList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($osNetAdapterListHTML)
|
|
}
|
|
|
|
if ($vswitchInfoNeeded)
|
|
{
|
|
$vswitchesListHTML = $titleHtmlVswitch + ($vswitchesList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($vswitchesListHTML)
|
|
}
|
|
|
|
if ($clusterDeployment -and $clusterConfigInfoNeeded)
|
|
{
|
|
$clusterConfigInfoListHTML = $titleHtmlClusterConfig + ($clusterConfigInfoList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($clusterConfigInfoListHTML)
|
|
}
|
|
|
|
if ($clusterDeployment -and $clusterNetworksInfoNeeded)
|
|
{
|
|
$clusterNetworksListHTML = $titleHtmlClusterNetworks + ($clusterNetworksList | ConvertTo-Html -Fragment)
|
|
[void]$dataHTML.Add($clusterNetworksListHTML)
|
|
}
|
|
|
|
$htmlReport = ConvertTo-Html -Head $header -Title $title -PostContent $postContent -Body $dataHTML
|
|
$htmlReport | Out-File $reportHtmlFile
|
|
|
|
}
|
|
|
|
#Sending the report via email
|
|
if ($emailReport -and $reportHtmlRequired)
|
|
{
|
|
switch ($emailSystem) {
|
|
msgraph
|
|
{ SendEmailReport-MSGraph -body (Out-String -InputObject $htmlReport) }
|
|
|
|
mailkit
|
|
{ SendEmailReport-Mailkit -body (Out-String -InputObject $htmlReport) }
|
|
|
|
Default {Write-Host -ForegroundColor Yellow "You must select an email system, msgraph or mailkit"}
|
|
}
|
|
|
|
|
|
}
|
|
|