Last active
October 18, 2025 11:36
-
-
Save Sharkrit/7589be27268a739dd223d8d1ffdec54c to your computer and use it in GitHub Desktop.
Revisions
-
Sharkrit revised this gist
Oct 18, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -11,7 +11,7 @@ param( [int]$HoursBack = 2, [string]$OutputRoot = $PWD ) Import-Module FailoverClusters -ErrorAction Stop -
Sharkrit renamed this gist
Oct 18, 2025 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
Sharkrit created this gist
Oct 18, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,134 @@ <# .SYNOPSIS Collect complete diagnostics for a Windows Failover Cluster including: Cluster config, Preferred Owners, RDMA, SMB, SR-IOV, Hyper-V, and Storage Spaces Direct (S2D) .NOTES Author: GPT-5 Requires: Administrator privilege, FailoverClusters, Hyper-V, Storage modules Usage: .\Collect-ClusterDiagnostics.ps1 -HoursBack 3 -OutputRoot "D:\ClusterDiag" #> param( [int]$HoursBack = 2, [string]$OutputRoot = "C:\ClusterDiag" ) Import-Module FailoverClusters -ErrorAction Stop Import-Module Hyper-V -ErrorAction SilentlyContinue Import-Module Storage -ErrorAction SilentlyContinue $timeStamp = Get-Date -Format "yyyyMMdd_HHmmss" $outputDir = Join-Path -Path $OutputRoot -ChildPath "ClusterDiag_$timeStamp" New-Item -Path $outputDir -ItemType Directory -Force | Out-Null Function Save-ToFile { param($Name, $Object) $path = Join-Path $outputDir $Name if ($Object -is [string]) { $Object | Out-File -FilePath $path -Encoding UTF8 } else { $Object | Out-String -Width 4096 | Out-File -FilePath $path -Encoding UTF8 } } # --- Core Cluster Info --- Write-Host "Collecting cluster configuration..." $cluster = Get-Cluster Save-ToFile "01_Cluster_Info.txt" $cluster Save-ToFile "02_Cluster_Nodes.txt" (Get-ClusterNode) Save-ToFile "03_Cluster_Networks.txt" (Get-ClusterNetwork) Save-ToFile "04_Cluster_Groups.txt" (Get-ClusterGroup | Select Name, OwnerNode, State, @{N='PreferredOwners';E={($_ | Get-ClusterOwnerNode) -join ','}}) Save-ToFile "05_Cluster_Resources.txt" (Get-ClusterResource) Save-ToFile "06_Cluster_Quorum.txt" (Get-ClusterQuorum) # --- RDMA / SR-IOV / NIC info --- $nodes = (Get-ClusterNode).Name foreach ($n in $nodes) { Write-Host "Collecting NIC/RDMA/SRIOV from $n..." $nicInfo = Invoke-Command -ComputerName $n -ScriptBlock { Get-NetAdapter | Select Name, InterfaceDescription, Status, LinkSpeed, VmqEnabled, SriovSupport, RDMAEnabled } $rdma = Invoke-Command -ComputerName $n -ScriptBlock { Get-NetAdapterRdma -ErrorAction SilentlyContinue } $sriov = Invoke-Command -ComputerName $n -ScriptBlock { Get-NetAdapterSriov -ErrorAction SilentlyContinue } Save-ToFile "Node_${n}_NICs.txt" $nicInfo Save-ToFile "Node_${n}_RDMA.txt" $rdma Save-ToFile "Node_${n}_SRIOV.txt" $sriov } # --- SMB & Storage Network --- Save-ToFile "07_SMB_ServerConfig.txt" (Get-SmbServerConfiguration) Save-ToFile "08_SMB_ServerNetworkInterface.txt" (Get-SmbServerNetworkInterface) Save-ToFile "09_SMB_Multichannel.txt" (Get-SmbMultichannelConnection -ErrorAction SilentlyContinue) # --- Hyper-V Section --- Write-Host "Collecting Hyper-V info..." foreach ($n in $nodes) { try { $vms = Invoke-Command -ComputerName $n -ScriptBlock { Get-VM | Select Name, State, CPUUsage, MemoryAssigned, Uptime, Version } $vSwitch = Invoke-Command -ComputerName $n -ScriptBlock { Get-VMSwitch | Select Name, SwitchType, BandwidthReservationMode, IovEnabled, IovQueuePairsRequested, Notes } $vNic = Invoke-Command -ComputerName $n -ScriptBlock { Get-VMNetworkAdapter -All | Select VMName, Name, MacAddress, SwitchName, IPAddresses, IsManagementOs } $vhd = Invoke-Command -ComputerName $n -ScriptBlock { Get-VMHardDiskDrive | Select VMName, Path, ControllerType, ControllerNumber } Save-ToFile "Node_${n}_HyperV_VMs.txt" $vms Save-ToFile "Node_${n}_HyperV_vSwitch.txt" $vSwitch Save-ToFile "Node_${n}_HyperV_vNIC.txt" $vNic Save-ToFile "Node_${n}_HyperV_VHDs.txt" $vhd } catch { Save-ToFile "Node_${n}_HyperV_Error.txt" $_ } } # --- S2D / Storage Spaces Direct --- Write-Host "Collecting S2D health and storage information..." try { $s2dHealth = Get-ClusterS2D Save-ToFile "10_S2D_ClusterS2D.txt" $s2dHealth Save-ToFile "11_S2D_HealthReport.txt" (Get-StorageSubSystem *cluster* | Get-StorageHealthReport) Save-ToFile "12_S2D_StoragePool.txt" (Get-StoragePool) Save-ToFile "13_S2D_VirtualDisks.txt" (Get-VirtualDisk) Save-ToFile "14_S2D_PhysicalDisks.txt" (Get-PhysicalDisk) Save-ToFile "15_S2D_CacheDevices.txt" (Get-PhysicalDisk | Where-Object { $_.Usage -eq 'Journal' }) Save-ToFile "16_S2D_Enclosures.txt" (Get-StorageEnclosure) Save-ToFile "17_S2D_FaultDomains.txt" (Get-StorageFaultDomain) Save-ToFile "18_S2D_Tiers.txt" (Get-StorageTier) } catch { Save-ToFile "S2D_Error.txt" $_ } # --- Performance Counters (S2D + CSV) --- Write-Host "Collecting performance counters (S2D + CSV)..." try { $csvPerf = Get-Counter '\Cluster CSVFS(* )\*' -ErrorAction SilentlyContinue $s2dPerf = Get-Counter '\Cluster Storage Spaces Direct(*)\*' -ErrorAction SilentlyContinue Save-ToFile "19_Perf_CSVFS.txt" $csvPerf Save-ToFile "20_Perf_S2D.txt" $s2dPerf } catch { Save-ToFile "Perf_Error.txt" $_ } # --- Event Logs --- $startTime = (Get-Date).AddHours(-$HoursBack) Write-Host "Collecting Event Logs from $startTime..." foreach ($n in $nodes) { try { $evtFailover = Invoke-Command -ComputerName $n -ScriptBlock { param($t) Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-FailoverClustering/Operational'; StartTime=$t} } -ArgumentList $startTime $evtHyperV = Invoke-Command -ComputerName $n -ScriptBlock { param($t) Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Hyper-V-Worker/Admin'; StartTime=$t} } -ArgumentList $startTime $evtS2D = Invoke-Command -ComputerName $n -ScriptBlock { param($t) Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-StorageSpaces-Driver/Operational'; StartTime=$t} } -ArgumentList $startTime Save-ToFile "Node_${n}_Evt_Failover.txt" $evtFailover Save-ToFile "Node_${n}_Evt_HyperV.txt" $evtHyperV Save-ToFile "Node_${n}_Evt_S2D.txt" $evtS2D } catch { Save-ToFile "Node_${n}_EventError.txt" $_ } } # --- Cluster Logs --- Write-Host "Generating cluster logs..." $clusterLogDir = Join-Path $outputDir "ClusterLogs" New-Item $clusterLogDir -ItemType Directory -Force | Out-Null Get-ClusterLog -Destination $clusterLogDir -UseLocalTime -Force | Out-Null # --- Compress results --- $zipPath = Join-Path $OutputRoot ("ClusterDiag_$timeStamp.zip") Compress-Archive -Path "$outputDir\*" -DestinationPath $zipPath -Force Write-Host "✅ Diagnostics complete." Write-Host "📂 Output folder: $outputDir" Write-Host "🗜️ Zipped file: $zipPath"