193 lines
6.6 KiB
PowerShell
193 lines
6.6 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Daily VMware Cluster metadata report for PowerBI trending and capacity planning.
|
|
|
|
.DESCRIPTION
|
|
Collects cluster-level metadata from vCenter including DRS/HA configuration,
|
|
aggregate compute capacity, and effective resource availability.
|
|
Exports a timestamped CSV and inserts into SQL each run.
|
|
Append daily runs to build a historical dataset for PowerBI trend analysis.
|
|
|
|
.NOTES
|
|
Run the following DDL once to create the destination table:
|
|
|
|
DROP TABLE IF EXISTS [dbo].[VMware_Trends_Cluster]
|
|
|
|
CREATE TABLE [dbo].[VMware_Trends_Cluster] (
|
|
[ReportDate] DATETIME2 NOT NULL,
|
|
[ClusterName] NVARCHAR(255) NOT NULL,
|
|
[Datacenter] NVARCHAR(100) NULL,
|
|
[DrsEnabled] BIT NOT NULL,
|
|
[DrsMode] NVARCHAR(50) NULL,
|
|
[HaEnabled] BIT NOT NULL,
|
|
[HostCount] INT NULL,
|
|
[EffectiveHostCount] INT NULL,
|
|
[TotalCpuCores] INT NULL,
|
|
[TotalCpuMhz] INT NULL,
|
|
[EffectiveCpuMhz] INT NULL,
|
|
[TotalMemoryGB] DECIMAL(10,2) NULL,
|
|
[EffectiveMemoryGB] DECIMAL(10,2) NULL,
|
|
[UsedMemoryGB] DECIMAL(10,2) NULL,
|
|
[VMCount] INT NULL
|
|
)
|
|
|
|
TotalCpuMhz, EffectiveCpuMhz, TotalMemoryGB, and EffectiveMemoryGB come from
|
|
vCenter's cluster summary (real-time aggregate).
|
|
UsedMemoryGB is summed from each host's current MemoryUsageGB.
|
|
TotalCpuCores is summed from each host's hardware CpuInfo.
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
)
|
|
|
|
Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro
|
|
|
|
#region --- Setup ---------------------------------------------------------------
|
|
[string] $OutputPath = 'C:\temp\VM_Trends\'
|
|
[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1'
|
|
[string] $Database = 'ITD-Systems-Automation'
|
|
[string] $Table = 'VMware_Trends_Cluster'
|
|
[System.Management.Automation.PSCredential] $SqlCredential = $Secret:sql_itdpsu1
|
|
|
|
$RunDate = Get-Date
|
|
$DateStamp = $RunDate.ToString('yyyyMMdd')
|
|
$Timestamp = $RunDate.ToString('yyyy-MM-dd')
|
|
|
|
if (-not (Test-Path -Path $OutputPath)) {
|
|
New-Item -ItemType Directory -Path $OutputPath | Out-Null
|
|
}
|
|
|
|
Start-Transcript -Path (Join-Path $OutputPath "ClusterMetadataReport_$DateStamp.log") -Append
|
|
|
|
#endregion
|
|
|
|
#region --- Build Cluster -> Datacenter Lookup ---------------------------------
|
|
|
|
Write-Verbose 'Building cluster-to-datacenter map...'
|
|
$ClusterDatacenterMap = @{}
|
|
|
|
Get-Datacenter | ForEach-Object {
|
|
$DatacenterName = $_.Name
|
|
Get-Cluster -Location $_ | ForEach-Object {
|
|
$ClusterDatacenterMap[$_.Name] = $DatacenterName
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region --- Collect Cluster Data -----------------------------------------------
|
|
|
|
Write-Verbose 'Gathering clusters...'
|
|
$AllClusters = Get-Cluster
|
|
|
|
Write-Verbose "Processing $($AllClusters.Count) clusters..."
|
|
|
|
$Results = foreach ($Cluster in $AllClusters) {
|
|
|
|
$Summary = $Cluster.ExtensionData.Summary # reuse for all summary fields
|
|
|
|
#--- Aggregate host-level stats that vCenter summary does not expose
|
|
$ClusterHosts = Get-VMHost -Location $Cluster
|
|
$TotalCpuCores = ($ClusterHosts | ForEach-Object {
|
|
$_.ExtensionData.Hardware.CpuInfo.NumCpuCores
|
|
} | Measure-Object -Sum).Sum
|
|
$UsedMemoryGB = [Math]::Round(
|
|
($ClusterHosts | Measure-Object -Property MemoryUsageGB -Sum).Sum, 2
|
|
)
|
|
$VMCount = ($ClusterHosts | ForEach-Object {
|
|
($_.ExtensionData.Vm | Measure-Object).Count
|
|
} | Measure-Object -Sum).Sum
|
|
|
|
#--- Capacity from cluster summary
|
|
$TotalCpuMhz = $Summary.TotalCpu # MHz
|
|
$EffectiveCpuMhz = $Summary.EffectiveCpu # MHz
|
|
$TotalMemoryGB = [Math]::Round($Summary.TotalMemory / 1GB, 2) # bytes -> GB
|
|
$EffectiveMemGB = [Math]::Round($Summary.EffectiveMemory / 1KB, 2) # MB -> GB
|
|
|
|
[PSCustomObject]@{
|
|
ReportDate = $Timestamp
|
|
ClusterName = $Cluster.Name
|
|
Datacenter = $ClusterDatacenterMap[$Cluster.Name]
|
|
DrsEnabled = $Cluster.DrsEnabled
|
|
DrsMode = $Cluster.DrsAutomationLevel
|
|
HaEnabled = $Cluster.HAEnabled
|
|
HostCount = $Summary.NumHosts
|
|
EffectiveHostCount = $Summary.NumEffectiveHosts
|
|
TotalCpuCores = [int]$TotalCpuCores
|
|
TotalCpuMhz = $TotalCpuMhz
|
|
EffectiveCpuMhz = $EffectiveCpuMhz
|
|
TotalMemoryGB = $TotalMemoryGB
|
|
EffectiveMemoryGB = $EffectiveMemGB
|
|
UsedMemoryGB = $UsedMemoryGB
|
|
VMCount = [int]$VMCount
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region --- Export CSV ---------------------------------------------------------
|
|
|
|
$OutputFile = Join-Path $OutputPath "ClusterMetadata_$DateStamp.csv"
|
|
$Results | Export-Csv -Path $OutputFile -NoTypeInformation
|
|
Write-Verbose "Exported $($Results.Count) cluster records to: $OutputFile"
|
|
|
|
#endregion
|
|
|
|
#region --- SQL Insert ---------------------------------------------------------
|
|
|
|
$DataTable = [System.Data.DataTable]::new()
|
|
|
|
$ColDefs = [ordered]@{
|
|
ReportDate = [datetime]
|
|
ClusterName = [string]
|
|
Datacenter = [string]
|
|
DrsEnabled = [bool]
|
|
DrsMode = [string]
|
|
HaEnabled = [bool]
|
|
HostCount = [int]
|
|
EffectiveHostCount = [int]
|
|
TotalCpuCores = [int]
|
|
TotalCpuMhz = [int]
|
|
EffectiveCpuMhz = [int]
|
|
TotalMemoryGB = [decimal]
|
|
EffectiveMemoryGB = [decimal]
|
|
UsedMemoryGB = [decimal]
|
|
VMCount = [int]
|
|
}
|
|
|
|
foreach ($Col in $ColDefs.GetEnumerator()) {
|
|
$Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value)
|
|
$Column.AllowDBNull = $true
|
|
[void]$DataTable.Columns.Add($Column)
|
|
}
|
|
|
|
foreach ($Row in $Results) {
|
|
$DataRow = $DataTable.NewRow()
|
|
foreach ($Col in $ColDefs.Keys) {
|
|
$Val = $Row.$Col
|
|
$DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value }
|
|
}
|
|
[void]$DataTable.Rows.Add($DataRow)
|
|
}
|
|
|
|
$SqlParams = @{
|
|
ServerInstance = $ServerInstance
|
|
DatabaseName = $Database
|
|
SchemaName = 'dbo'
|
|
TableName = $Table
|
|
Credential = $SqlCredential
|
|
InputData = $DataTable
|
|
}
|
|
Write-SqlTableData @SqlParams
|
|
|
|
Write-Verbose "Inserted $($DataTable.Rows.Count) cluster records into [$Database].[dbo].[$Table]"
|
|
|
|
#endregion
|
|
|
|
Disconnect-ITDvCenter
|
|
|
|
#region --- Cleanup -------------------------------------------------------------
|
|
Stop-Transcript
|
|
|
|
#endregion
|