Files
Hyper-V-Report-tsmagnum/Functions.ps1
Federico Lillacci 55ad4348a3 Add files via upload
2025-11-19 15:59:04 +01:00

604 lines
20 KiB
PowerShell

#DO NOT MODIFY
function Get-VmHostInfo
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vmHosts
)
$vmHostsList = [System.Collections.ArrayList]@()
foreach ($vmHost in $vmHosts)
{
$hostInfos = Get-CimInstance Win32_OperatingSystem -ComputerName $vmHost.ComputerName
$vhdPathDrive = (Get-VMHost).VirtualHardDiskPath.Split(":")[0]
$hypervInfo = [PSCustomObject]@{
Name = $vmHost.ComputerName
LogicalCPU = $vmHost.LogicalProcessorCount
RAM_GB = [System.Math]::round((($vmHost.MemoryCapacity)/1GB),2)
Free_RAM_GB = [System.Math]::round((($hostInfos).FreePhysicalMemory/1MB),2)
VHD_Volume = $vhdPathDrive+":"
Free_VHD_Vol_GB = [System.Math]::round(((Get-Volume $vhdPathDrive -CimSession $vmHost.ComputerName).SizeRemaining/1GB),2)
LiveMig = $vmHost.VirtualMachineMigrationEnabled
Last_Boot = $hostInfos.LastBootUpTime.ToString('dd/MM/yy HH:mm')
OsBuild = Get-OsBuildLevel -vmHost $vmHost.ComputerName
}
[void]$vmHostsList.Add($hypervInfo)
}
return $vmHostsList
}
function Get-VHDXInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vms
)
$vhdxList = [System.Collections.ArrayList]@()
foreach ($vm in $vms)
{
$vhdxs = Get-VHD -VMId $vm.VMId -ComputerName $vm.ComputerName |`
Select-Object ComputerName,Path,VhdFormat,VhdType,FileSize,Size,FragmentationPercentage
foreach ($vhdx in $vhdxs)
{
$vhdxInfo = [PSCustomObject]@{
Host = $vhdx.ComputerName
VM = $vm.VMName
Path = $vhdx.Path
Format = $vhdx.VhdFormat
Type = $vhdx.VhdType
File_Size_GB = [System.Math]::round(($vhdx.FileSize/1GB),2)
Size_GB = $vhdx.Size/1GB
Frag_Perc = $vhdx.FragmentationPercentage
}
[void]$vhdxList.Add($vhdxInfo)
}
}
return $vhdxList
}
function Get-VmnetInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vms
)
$vmnetAdapterList = [System.Collections.ArrayList]@()
foreach ($vm in $vms)
{
$vmnetadapts = Get-VMNetworkAdapter -vm $vm |`
Select-Object MacAddress,Connected,VMName,IsSynthetic,IPAddresses,SwitchName,Status,VlanSetting
foreach ($vmnetadapt in $vmnetadapts)
{
$vmnetAdaptInfo = [PSCustomObject]@{
VM = $vmnetadapt.VMName
MAC = $vmnetadapt.MacAddress
IP_Addr = $vmnetadapt.IPAddresses | Out-String
Connected = $vmnetadapt.Connected
vSwitch = $vmnetadapt.SwitchName
#Status = $vmnetadapt.Status.
Vlan_Mode = $vmnetadapt.VlanSetting.OperationMode
Vlan_Id = $vmnetadapt.VlanSetting.AccessVlanId
}
[void]$vmnetAdapterList.Add($vmnetAdaptInfo)
}
}
return $vmnetAdapterList
}
function Get-CsvHealth
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $clusterNodes
)
$csvHealthList = [System.Collections.ArrayList]@()
foreach ($clusterNode in $clusterNodes)
{
$csvHealth = Get-ClusterSharedVolumeState -Node $clusterNode.NodeName |`
Select-Object Node,VolumeFriendlyName,Name,StateInfo
foreach ($csv in $csvHealth)
{
$csvHealthVol = [PSCustomObject]@{
Node = $csv.Node
Volume = $csv.VolumeFriendlyName
Disk = $csv.Name
State = $csv.StateInfo
}
[void]$csvHealthList.Add($csvHealthVol)
}
}
return $csvHealthList
}
function Get-CsvSpaceUtilization {
[CmdletBinding()]
$csvSpaceList = [System.Collections.ArrayList]@()
$csvVolumes = Get-Volume | Where-Object {$_.FileSystem -match "CSVFS"} |`
Select-Object FileSystemLabel,HealthStatus,Size,SizeRemaining
foreach ($csvVolume in $csvVolumes)
{
$csvInfo = [PSCustomObject]@{
Volume = $csvVolume.FileSystemLabel
Health = $csvVolume.HealthStatus
Size_GB = [System.Math]::round(($csvVolume.Size/1GB),2)
Free_GB = [System.Math]::round(($csvVolume.SizeRemaining/1GB),2)
Used_Perc = [System.Math]::round(((($csvVolume.Size - $csvVolume.SizeRemaining)/$csvVolume.Size)*100),2)
}
[void]$csvSpaceList.Add($csvInfo)
}
return $csvSpaceList
}
function Get-VmInfo
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vm
)
$vmInfo = [PSCustomObject]@{
Name = $vm.Name
Host = $vm.ComputerName
Gen = $vm.Generation
Version = $vm.Version
vCPU = $vm.ProcessorCount
RAM_Assigned = [System.Math]::round((($vm.MemoryAssigned)/1GB),2)
RAM_Demand = [System.Math]::round((($vm.MemoryDemand)/1GB),2)
Dyn_Memory = $vm.DynamicMemoryEnabled
IP_Addr_NIC0 = $vm.NetworkAdapters[0].IPAddresses[0]
Snapshots = (Get-VMSnapshot -VMName $vm.Name -ComputerName $vm.ComputerName).Count
Clustered = $vm.IsClustered
State = $vm.State
Heartbeat = $vm.Heartbeat
Uptime = $vm.Uptime.ToString("dd\.hh\:mm")
Replication = $vm.ReplicationState
Creation_Time = $vm.CreationTime
}
return $vmInfo
}
function Get-SnapshotInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vms
)
$vmSnapshotsList = [System.Collections.ArrayList]@()
foreach ($vm in $vms)
{
$foundSnapshots = Get-VMSnapshot -VMName $vm.name -ComputerName $vm.ComputerName
if (($foundSnapshots).Count -gt 0)
{
foreach ($foundSnapshot in $foundSnapshots)
{
$snapInfo = [PSCustomObject]@{
VM = $foundSnapshot.VMName
Name = $foundSnapshot.Name
Creation_Time = $foundSnapshot.CreationTime
Age_Days = $today.Subtract($foundSnapshot.CreationTime).Days
Parent_Snap = $foundSnapshot.ParentSnapshotName
}
[void]$vmSnapshotsList.Add($snapInfo)
}
}
else
{
$snapInfo = [PSCustomObject]@{
VM = $vm.VMName
Name = "No snapshots found"
Creation_Time = "N/A"
Age_Days = "N/A"
Parent_Snap = "No snapshots found"
}
[void]$vmSnapshotsList.Add($snapInfo)
}
}
return $vmSnapshotsList
}
function Get-ReplicationInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vms
)
$replicationsList = [System.Collections.ArrayList]@()
#Getting the Replication status
$replicatedVms = ($vms | Where-Object {$_.ReplicationState -ne "Disabled"} | Select-Object -Unique)
if (($replicatedVms).Count -gt 0)
{
foreach ($vm in $replicatedVms)
{
$replication = Get-VmReplication -Vmname $vm.VMName |`
Select-Object Name,State,Health,LastReplicationTime,PrimaryServer,ReplicaServer,AuthType
[void]$replicationsList.Add($replication)
}
}
#Creating a dummy object to correctly format the HTML report with no replications
else
{
$statusMsg = "No replicated VMs found!"
$noReplicationInfo = [PSCustomObject]@{
Replication_Infos = $statusMsg
}
[void]$replicationsList.Add($noReplicationInfo)
}
return $replicationsList
}
function Get-OsNetAdapterInfo
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vmHosts
)
$osNetadaptsList = @()
foreach ($vmHost in $vmHosts)
{
$osNetadaptsArray = @()
$osNetadapts = Get-VMNetworkAdapter -ManagementOS -ComputerName $vmHost.Name |`
Select-Object ComputerName,Name,MacAddress,IPAddresses,SwitchName,Status,VlanSetting
foreach ($osNetadapt in $osNetadapts)
{
$osNetAdaptInfo = [PSCustomObject]@{
Host = $osNetadapt.ComputerName
Name = $osNetadapt.Name
MAC = $osNetadapt.MacAddress
IP_Addr = Get-MgmtOsNicIpAddr -adapterName $osNetadapt.Name -vmHost $vmHost | Out-String
vSwitch = $osNetadapt.SwitchName
Status = $osNetadapt.Status | Out-String
Vlan_Mode = $osNetadapt.VlanSetting.OperationMode
Vlan_Id = $osNetadapt.VlanSetting.AccessVlanId
}
$osNetadaptsArray += $osNetAdaptInfo
}
$osNetadaptsList += $osNetadaptsArray
}
return $osNetadaptsList
}
function Get-VswitchInfo
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vmHosts
)
$vswitchesList = @()
foreach ($vmHost in $vmHosts)
{
$vswitches = Get-VMSwitch -ComputerName $vmHost.Name | `
Select-Object ComputerName,Name,EmbeddedTeamingEnabled,SwitchType,AllowManagementOS
$vswitchesArray = @()
foreach ($vswitch in $vswitches)
{
$vswitchInfo = [PSCustomObject]@{
Host = $vswitch.ComputerName
Virtual_Switch = $vswitch.Name
SET = $vswitch.EmbeddedTeamingEnabled
Uplinks = Get-VswitchMember -vswitch $vswitch.Name
Type = $vswitch.SwitchType
Mgmt_OS_Allowed = $vswitch.AllowManagementOS
}
$vswitchesArray += $vswitchInfo
}
$vswitchesList += $vswitchesArray
}
return $vswitchesList
}
function Get-MgmtOsNicIpAddr
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $adapterName,
[Parameter(Mandatory = $true)] $vmHost
)
$ipAddr = (Get-NetIPAddress -CimSession $vmHost.Name |`
Where-Object {$_.InterfaceAlias -like "*($($adapterName))" -and $_.AddressFamily -eq 'IPv4'}).IPAddress
return $ipAddr
}
function Get-VswitchMember
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vswitch
)
$targetSwitch = Get-VMSwitch -Name $vswitch
$vswitchMembers = ($targetSwitch.NetAdapterInterfaceDescriptions)
$physNics = [System.Collections.ArrayList]@()
foreach ($vswitchMember in $vswitchMembers)
{
$physNic = (Get-Netadapter -InterfaceDescription $vswitchMember).Name
[void]$physNics.Add($physNic)
}
$vswitchPhysNics = $physNics | Out-String
return $vswitchPhysNics
}
function Get-ClusterConfigInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false)] $cluster = "."
)
$cluster = Get-Cluster -Name $cluster | Select-Object Name,Domain
$clusterConfigInfoList = [PSCustomObject]@{
Cluster_Name = $cluster.Name
Cluster_Domain = $cluster.Domain
}
return $clusterConfigInfoList
}
function Get-ClusterNetworksInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false)] $cluster = "."
)
$clusterNets = Get-ClusterNetwork -Cluster $cluster | Select-Object Name,Role,State,Address,Autometric,Metric
$clusterNetworksList = [System.Collections.ArrayList]@()
foreach ($clusterNet in $clusterNets)
{
$clusterNetInfo = [PSCustomObject]@{
Name = $clusterNet.Name
Role = $clusterNet.Role
State = $clusterNet.State
Address = $clusterNet.Address
Autometric = $clusterNet.Autometric
Metric = $clusterNet.Metric
}
[void]$clusterNetworksList.Add($clusterNetInfo)
}
return $clusterNetworksList
}
function Get-OsBuildLevel
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $vmHost
)
$code = {
Try
{
$osBuildLevel = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name LCUver -Verbose).LCUVer
return $osBuildLevel
}
Catch
{
$osBuildLevel = "N/A"
return $osBuildLevel
}
}
if ($vmHost -eq $env:COMPUTERNAME)
{
$osBuildLevel = Invoke-Command -ScriptBlock $code
}
else
{
$osBuildLevel = Invoke-Command -ComputerName $vmHost -ScriptBlock $code -Verbose
}
return $osBuildLevel
}
function Import-SafeCreds {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $encryptedSMTPCredsFile
)
$credentials = Import-Clixml -Path $encryptedSMTPCredsFile
return $credentials
}
function SendEmailReport-MSGraph
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $body
)
#Checking if required module is present; if not, install it
if (!(Get-Module -Name Microsoft.Graph -ListAvailable))
{
Write-Host -ForegroundColor Yellow "MS Graph module missing, installing..."
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force
Import-Module -Name Microsoft.Graph
}
#Connect interactively to Microsoft Graph with required permissions
Connect-MgGraph -NoWelcome -Scopes 'Mail.Send', 'Mail.Send.Shared'
if ($ccrecipient)
{
$params = @{
Message = @{
Subject = $subject
Body = @{
ContentType = $type
Content = $body
}
ToRecipients = @(
@{
EmailAddress = @{
Address = $reportRecipient
}
}
)
CcRecipients = @(
@{
EmailAddress = @{
Address = $ccrecipient
}
}
)
}
SaveToSentItems = $save
}
}
else
{
$params = @{
Message = @{
Subject = $subject
Body = @{
ContentType = $type
Content = $body
}
ToRecipients = @(
@{
EmailAddress = @{
Address = $reportRecipient
}
}
)
}
SaveToSentItems = $save
}
}
# Send message
Send-MgUserMail -UserId $reportSender -BodyParameter $params
}
function SendEmailReport-Mailkit
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)] $body
)
#Checking if required module is present; if not, install it
if (!(Get-Module -ListAvailable -Name "Send-MailKitMessage"))
{
Write-Host -ForegroundColor Yellow "Send-MailKitMessage module missing, installing..."
Install-Module -Name "Send-MailKitMessage" -Scope CurrentUser -Force
}
Import-Module -Name "Send-MailKitMessage"
$UseSecureConnectionIfAvailable = $true
if ($encryptedSMTPCreds)
{
$Credentials = Import-SafeCreds -encryptedSMTPCredsFile $encryptedSMTPCredsFile
}
else
{
$credentials = `
[System.Management.Automation.PSCredential]::new($smtpServerUser, `
(ConvertTo-SecureString -String $smtpServerPwd -AsPlainText -Force))
}
$from = [MimeKit.MailboxAddress]$reportSender
$recipientList = [MimeKit.InternetAddressList]::new()
$recipientList.Add([MimeKit.InternetAddress]$reportRecipient)
if ($ccrecipient)
{
$ccList = [MimeKit.InternetAddressList]::new();
$ccList.Add([MimeKit.InternetAddress]$ccrecipient);
}
$Parameters = @{
"UseSecureConnectionIfAvailable" = $UseSecureConnectionIfAvailable
"Credential" = $credentials
"SMTPServer" = $smtpServer
"Port" = $smtpServerPort
"From" = $from
"RecipientList" = $recipientList
"CCList" = $ccList
"Subject" = $subject
"HTMLBody" = $body
}
Send-MailKitMessage @Parameters
}