From 4410d47e154e886f898fc881183cc633d13170a3 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Tue, 5 Dec 2017 22:20:19 -0600 Subject: [PATCH 01/15] Initial progress towards #1 and slowly converting Diag-V over to module format - still a lot left to convert --- CSVs/Get-CSVtoPhysicalDiskMapping.ps1 | 92 -- CSVs/Get-FileSizes.ps1 | 99 -- Diag-V.ps1 | 1858 ---------------------- Diag-V.psd1 | 103 ++ Diag-V.psm1 | 1804 +++++++++++++++++++++ Overallocation/Test-HyperVAllocation.ps1 | 522 ------ README.md | 2 + VMs/Get-IntegrationServicesCheck.ps1 | 166 -- VMs/Get-VMLocationPathInfo.ps1 | 137 -- VMs/Get-VMStatus.ps1 | 240 --- VMs/VHDInfo/Get-SharedVHDs.ps1 | 129 -- VMs/VHDInfo/Get-VMAllVHDs.ps1 | 227 --- 12 files changed, 1909 insertions(+), 3470 deletions(-) delete mode 100644 CSVs/Get-CSVtoPhysicalDiskMapping.ps1 delete mode 100644 CSVs/Get-FileSizes.ps1 delete mode 100644 Diag-V.ps1 create mode 100644 Diag-V.psd1 create mode 100644 Diag-V.psm1 delete mode 100644 Overallocation/Test-HyperVAllocation.ps1 delete mode 100644 VMs/Get-IntegrationServicesCheck.ps1 delete mode 100644 VMs/Get-VMLocationPathInfo.ps1 delete mode 100644 VMs/Get-VMStatus.ps1 delete mode 100644 VMs/VHDInfo/Get-SharedVHDs.ps1 delete mode 100644 VMs/VHDInfo/Get-VMAllVHDs.ps1 diff --git a/CSVs/Get-CSVtoPhysicalDiskMapping.ps1 b/CSVs/Get-CSVtoPhysicalDiskMapping.ps1 deleted file mode 100644 index 38f9ef4..0000000 --- a/CSVs/Get-CSVtoPhysicalDiskMapping.ps1 +++ /dev/null @@ -1,92 +0,0 @@ -<# -.Synopsis - Resolves CSV to a physicalDisk drive -.DESCRIPTION - Discovers all cluster shared volumes associated with the specificed cluster - Resolves all cluster shared volumes to physical drives and pulls usefull - information about the characteristcs of the associated physical drive -.EXAMPLE - Get-CSVtoPhysicalDiskMapping - - This command retrieves all cluster shared volumes and pulls information - related to the physical disk associated with each CSV. Since no cluster name - is specified this command resolves to a locally available cluster (".") -.EXAMPLE - Get-CSVtoPhysicalDiskMappying -clusterName "Clus1.domain.local" - - This command retrieves all cluster shared volumes and pulls information related - to the physical disk associated with the CSVs that are associated with the - Clus1.domain.local cluster. -.OUTPUTS - #CSVName : Cluster Disk 1 - #CSVPartitionNumber : 2 - #Size (GB) : 1500 - #CSVOwnerNode : node1 - #FreeSpace (GB) : 697 - #CSVVolumePath : C:\ClusterStorage\Volume1 - #CSVPhysicalDiskNumber : 3 - #Perecent Free : 46.49729 -.NOTES - Adapted from code written by Ravikanth Chaganti http://www.ravichaganti.com - Enhanced by: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following information for each CSV in the cluster: - CSV Name - Total Size of associated physical disk - CSV Volume Path - Percent free of physical disk - VERY useful - CSV Owner Node - CSV Partition Number - Freespace in (GB) -#> -function Get-CSVtoPhysicalDiskMapping{ - [cmdletbinding()] - Param - ( - #clusterName should be the FQDN of your cluster, if not specified it will - [Parameter(Mandatory = $false, - ValueFromPipeline = $false, - ValueFromPipelineByPropertyName = $true, - Position = 0)] - [string] - $clusterName = "." - ) - try{ - $clusterSharedVolume = Get-ClusterSharedVolume -Cluster $clusterName ` - -ErrorAction SilentlyContinue - if ($clusterSharedVolume -eq $null){ - Write-Host "No CSVs discovered - script has completed" ` - -ForegroundColor Yellow - } - else{ - foreach ($volume in $clusterSharedVolume) { - $volumeowner = $volume.OwnerNode.Name - $csvVolume = $volume.SharedVolumeInfo.Partition.Name - $cimSession = New-CimSession -ComputerName $volumeowner - $volumeInfo = Get-Disk -CimSession $cimSession | Get-Partition | ` - Select DiskNumber, @{Name="Volume"; ` - Expression={Get-Volume -Partition $_ | ` - Select -ExpandProperty ObjectId} - } - $csvdisknumber = ($volumeinfo | where ` - { $_.Volume -eq $csvVolume}).Disknumber - $csvtophysicaldisk = New-Object -TypeName PSObject -Property @{ - "CSVName" = $volume.Name - "Size (GB)" = [int]($volume.SharedVolumeInfo.Partition.Size/1GB) - "CSVVolumePath" = $volume.SharedVolumeInfo.FriendlyVolumeName - "Perecent Free" = $volume.SharedVolumeInfo.Partition.PercentFree - "CSVOwnerNode"= $volumeowner - "CSVPhysicalDiskNumber" = $csvdisknumber - "CSVPartitionNumber" = $volume.SharedVolumeInfo.PartitionNumber - "FreeSpace (GB)" = [int]($volume.SharedVolumeInfo.Partition.Freespace/1GB) - } - $csvtophysicaldisk - } - } - } - catch{ - Write-Host "ERROR - An issue was encountered getting physical disks of CSVs:" ` - -ForegroundColor Red - Write-Error $_ - } -} \ No newline at end of file diff --git a/CSVs/Get-FileSizes.ps1 b/CSVs/Get-FileSizes.ps1 deleted file mode 100644 index f87e440..0000000 --- a/CSVs/Get-FileSizes.ps1 +++ /dev/null @@ -1,99 +0,0 @@ -<# -.Synopsis - Scans specified path and gets total size as well as top 10 largest files -.DESCRIPTION - Recursively scans all files in the specified path. It then gives a total - size in GB for all files found under the specified location as well as - the top 10 largest files discovered. The length of scan completion is - impacted by the size of the path specified as well as the number of files -.EXAMPLE - Get-FileSizes -path C:\temp - - This command recursively scans the specified path and will tally the total - size of all discovered files as well as the top 10 largest files. -.OUTPUTS - Scan results for: c:\ - ---------------------------------------------- - Total size of all files: 175 GB. - ---------------------------------------------- - Top 10 Largest Files found: - - Directory Name Length - --------- ---- ------ - C:\rs-pkgs ManagementPC.vhdx 28.19 - C:\rs-pkgs CentOS-7-x86_64-Everything-1503-01.iso 7.07 - C:\ hiberfil.sys 6.38 - C:\rs-pkgs en_windows_10_multiple_editions_x64_dvd_6846432.iso 3.8 - C:\rs-pkgs UbuntuServer14.vhdx 3.6 - C:\GOG Games\The Witcher 3 Wild Hunt\content\content0 texture.cache 3.24 - C:\GOG Games\The Witcher 3 Wild Hunt\content\content4\bundles movies.bundle 3.23 - C:\Program Files (x86)\StarCraft II\Campaigns\Liberty.SC2Campaign Base.SC2Assets 3.16 - C:\Program Files (x86)\StarCraft II\Mods\Liberty.SC2Mod Base.SC2Assets 2.42 - C:\ pagefile.sys 2.38 - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following information for the specified path: - Total size of all files found under the path - Top 10 largest files discovered -#> -function Get-FileSizes{ - [cmdletbinding()] - Param ( - #directory path that you wish to scan - [Parameter(Mandatory = $true, - HelpMessage = "Please enter a path (Ex: C:\ClusterStorage\Volume1)", - ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true, Position = 0) - ] - [string]$path - ) - - Write-Host "Note - depending on how many files are in the path you specified "` - "this scan can take some time. Patience please..." -ForegroundColor Gray - #test path and then load location - try{ - $check = Test-Path $path - if($check -eq $true){ - $files = Get-ChildItem -Path $path -Recurse -Force ` - -ErrorAction SilentlyContinue - } - else{ - Write-Host "The path you specified is not valid" -ForegroundColor Red - return - } - } - catch{ - Write-Error $_ - } - [double]$intSize = 0 - try{ - #get total size of all files - foreach ($objFile in $files){ - $i++ - $intSize = $intSize + $objFile.Length - Write-Progress -activity "Adding File Sizes" -status "Percent added: " ` - -PercentComplete (($i / $files.length) * 100) - } - $intSize = [math]::round($intSize / 1GB, 0) - #generate output - Write-Host "Scan results for: $path" -ForegroundColor Cyan - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "Total size of all files: $intSize GB." ` - -ForegroundColor Magenta - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "Top 10 Largest Files found:" -ForegroundColor Cyan - $files | select Directory,Name,` - @{Label=”Length”;Expression={[math]::round($_.Length/1GB, 2)}} | ` - sort Length -Descending| select -First 10 | ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - catch{ - Write-Error $_ - } - -} \ No newline at end of file diff --git a/Diag-V.ps1 b/Diag-V.ps1 deleted file mode 100644 index 2c0aede..0000000 --- a/Diag-V.ps1 +++ /dev/null @@ -1,1858 +0,0 @@ -<# .Synopsis Collection of several Hyper-V diagnostics that can be run via a simple choice menu .DESCRIPTION Diag-V is a collection of various Hyper-V diagnostics. It presents the user a simple choice menu that allows the user to select and execute the desired diagnostic. Each diagnostic is a fully independent function which can be copied and run independent of Diag-V if desired. .EXAMPLE Diag-V Copy code into an administrative PS or ISE window and run. .OUTPUTS Output will vary depending on the selected diagnostic. ############################################## - ____ _ __ __ - | _ \(_) __ _ __ _ \ \ / / - | | | | |/ _ |/ _ |____\ \ / / - | |_| | | (_| | (_| |_____\ V / - |____/|_|\__,_|\__, | \_/ - |___/ - ############################################## - A Hyper-V diagnostic utility - ############################################## - MAIN MENU - ############################################## - [1] VMs - [2] VHDs - [3] Overallocation - [4] CSVs - Please select a menu number: .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info .FUNCTIONALITY Get-VMStatus - ------------------------------ - Get-VMLocationPathInfo - ------------------------------ - Get-IntegrationServicesCheck - ------------------------------ - Get-VMAllVHDs - ------------------------------ - Get-SharedVHDs - ------------------------------ - Test-HyperVAllocation - ------------------------------ - Get-CSVtoPhysicalDiskMapping - ------------------------------ - Get-FileSizes #> -function Diag-V{ - #all this serves to do is to launch the parent menu choice option - showTheTopLevel -} -#################################################################################### -#------------------------------Menu Selections-------------------------------------- -#################################################################################### -<# -.Synopsis - showTheTopLevel is a menu level function that shows the parent (or top) menu choices -.DESCRIPTION - showTheTopLevel is a menu level function that shows the parent (or top) menu choices -#> -function showTheTopLevel{ - Clear-Host - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " ____ _ __ __" -ForegroundColor Yellow - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Yellow - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Yellow - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Yellow - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Yellow - Write-Host " |___/ " -ForegroundColor Yellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkYellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " MAIN MENU" -ForegroundColor DarkGreen - Write-Host "##############################################" -ForegroundColor Cyan - - Write-Host "[1] VMs" -ForegroundColor Green -BackgroundColor Black - Write-Host "[2] VHDs" -ForegroundColor Green -BackgroundColor Black - Write-Host "[3] Overallocation" -ForegroundColor Green -BackgroundColor Black - Write-Host "[4] CSVs" -ForegroundColor Green -BackgroundColor Black - - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if($topLevel -eq 1){ - showVMDiags - } - elseif($topLevel -eq 2){ - showVHDDiags - } - elseif($topLevel -eq 3){ - showAllocationDiags - } - elseif($topLevel -eq 4){ - showCSVDiags - } - else{ - Write-Host "You failed to select one of the available choices" -ForegroundColor Red - } -} -<# -.Synopsis - showTheTopLevel is a menu level function that shows the VM diagnostic menu choices -.DESCRIPTION - showTheTopLevel is a menu level function that shows the VM diagnostic menu choices -#> -function showVMDiags{ - Clear-Host - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " ____ _ __ __" -ForegroundColor Yellow - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Yellow - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Yellow - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Yellow - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Yellow - Write-Host " |___/ " -ForegroundColor Yellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkYellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " VM Diagnostics" -ForegroundColor DarkGreen - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "[1] Get-VMStatus" -ForegroundColor Green -BackgroundColor Black - Write-Host "[2] Get-VMLocationPathInfo" -ForegroundColor Green -BackgroundColor Black - Write-Host "[3] Get-IntegrationServicesCheck" -ForegroundColor Green -BackgroundColor Black - Write-Host "[4] Main Menu" -ForegroundColor Green -BackgroundColor Black - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if($topLevel -eq 1){ - Get-VMStatus - } - elseif($topLevel -eq 2){ - Get-VMLocationPathInfo - } - elseif($topLevel -eq 3){ - Get-IntegrationServicesCheck - } - elseif($topLevel -eq 4){ - showTheTopLevel - } - else{ - Write-Host "You failed to select one of the available choices" -ForegroundColor Red - } -} -<# -.Synopsis - showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices -.DESCRIPTION - showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices -#> -function showVHDDiags{ - Clear-Host - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " ____ _ __ __" -ForegroundColor Yellow - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Yellow - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Yellow - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Yellow - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Yellow - Write-Host " |___/ " -ForegroundColor Yellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkYellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " VHD Diagnostics" -ForegroundColor DarkGreen - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "[1] Get-VMAllVHDs" -ForegroundColor Green -BackgroundColor Black - Write-Host "[2] Get-SharedVHDs" -ForegroundColor Green -BackgroundColor Black - Write-Host "[3] Main Menu" -ForegroundColor Green -BackgroundColor Black - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if($topLevel -eq 1){ - Get-VMAllVHDs - } - elseif($topLevel -eq 2){ - Get-SharedVHDs - } - elseif($topLevel -eq 3){ - showTheTopLevel - } - else{ - Write-Host "You failed to select one of the available choices" -ForegroundColor Red - } -} -<# -.Synopsis - showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices -.DESCRIPTION - showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices -#> -function showAllocationDiags{ - Clear-Host - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " ____ _ __ __" -ForegroundColor Yellow - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Yellow - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Yellow - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Yellow - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Yellow - Write-Host " |___/ " -ForegroundColor Yellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkYellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " OverAllocation Diagnostics" -ForegroundColor DarkGreen - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "[1] Test-HyperVAllocation" -ForegroundColor Green -BackgroundColor Black - Write-Host "[2] Main Menu" -ForegroundColor Green -BackgroundColor Black - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if($topLevel -eq 1){ - Test-HyperVAllocation - } - elseif($topLevel -eq 2){ - showTheTopLevel - } - else{ - Write-Host "You failed to select one of the available choices" -ForegroundColor Red - } -} -<# -.Synopsis - showCSVDiags is a menu level function that shows the CSV diagnostic menu choices -.DESCRIPTION - showCSVDiags is a menu level function that shows the CSV diagnostic menu choices -#> -function showCSVDiags{ - Clear-Host - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " ____ _ __ __" -ForegroundColor Yellow - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Yellow - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Yellow - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Yellow - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Yellow - Write-Host " |___/ " -ForegroundColor Yellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkYellow - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host " CSV Diagnostics" -ForegroundColor DarkGreen - Write-Host "##############################################" -ForegroundColor Cyan - Write-Host "[1] Get-CSVtoPhysicalDiskMapping" -ForegroundColor Green -BackgroundColor Black - Write-Host "[2] Get-FileSizes" -ForegroundColor Green -BackgroundColor Black - Write-Host "[3] Main Menu" -ForegroundColor Green -BackgroundColor Black - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if($topLevel -eq 1){ - Get-CSVtoPhysicalDiskMapping - } - elseif($topLevel -eq 2){ - Get-FileSizes - } - elseif($topLevel -eq 3){ - showTheTopLevel - } - else{ - Write-Host "You failed to select one of the available choices" -ForegroundColor Red - } -} -#################################################################################### -#-----------------------------END Menu Selections----------------------------------- -#################################################################################### - -#################################################################################### -#------------------------------Diagnostic FUNCTIONS--------------------------------- -#################################################################################### -<# -.Synopsis - Name, State, CPUUsage, Memory usage, Uptime, and Status of all VMs on a - cluster or standalone hyp -.DESCRIPTION - Gets the status of all discovered VMs. Automatically detects if running on a - standalone hyp or hyp cluster. If standalone is detected it will display VM - status information for all VMs on the hyp. If a cluster is detected it will - display VM status information for each node in the cluster. -.EXAMPLE - Get-VMStatus - - This command will automatically detect a standalone hyp or hyp cluster and - will retrieve VM status information for all detected nodes. -.OUTPUTS - Cluster detected. Executing cluster appropriate diagnostic... - ---------------------------------------------- - RUNNING VMs - ---------------------------------------------- - HypV1 - No VMs are present on this node. - ---------------------------------------------- - Hypv2 - There are no running VMs - probably not a good thing. Fix it. - ---------------------------------------------- - - - ---------------------------------------------- - NOT RUNNING VMs - ---------------------------------------------- - HypV1 - No VMs are present on this node. - ---------------------------------------------- - Hypv2 - - Name State CPUUsage(%) MemoryAssigned(M) Uptime Status - ---- ----- ----------- ----------------- ------ ------ - 2008R2Clust Off 0 0 00:00:00 Operating normally - 2008R2Clust2 Off 0 0 00:00:00 Operating normally - 2012R2Clust Off 0 0 00:00:00 Operating normally - 2012R2Clust2 Off 0 0 00:00:00 Operating normally - Web1 Off 0 0 00:00:00 Operating normally - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: - Name - State - CPUUsage - Memory - Uptime - Status -#> -#it will automatically detect standalone or cluster and will run the appropriate diagnostic -function Get-VMStatus{ - Write-Host "This will not find any VMs if you are not running PowerShell as admin!" ` - -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #------------------------------------------------------------------------ - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "RUNNING VMs" -ForegroundColor Green ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Foreach($node in $nodes){ - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - #-----------------Get VM Data Now--------------------- - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $running = Get-VM -ComputerName $node.name | ` - where {$_.state -eq 'running'} | sort Uptime | ` - select Name,State,CPUUsage,` - @{N="MemoryMB";E={$_.MemoryAssigned/1MB}},Uptime,Status,` - IsClustered| ft -AutoSize - if($running -ne $null){ - $running - } - else{ - Write-Host "There are no running VMs - probably not a good thing."` - " Fix it." -ForegroundColor White -BackgroundColor Black - } - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------END Get VM Data --------------------- - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - Write-Host "`n" - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "NOT RUNNING VMs" -ForegroundColor Red ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Foreach($node in $nodes){ - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - Write-Host $node.name -ForegroundColor White ` - -BackgroundColor Black - #-----------------Get VM Data Now--------------------- - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $notrunning = Get-VM -ComputerName $node.name | ` - where {$_.state -ne 'running'} | ` - select Name,State,CPUUsage,` - @{N="MemoryMB";E={$_.MemoryAssigned/1MB}},Status,` - IsClustered| ft -AutoSize | ft -AutoSize - if($notrunning -ne $null){ - $notrunning - } - else{ - Write-Host "All VMs are currently running - HOORAY!" ` - -ForegroundColor White -BackgroundColor Black - } - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------END Get VM Data --------------------- - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - #------------------------------------------------------------------------ - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #-----------------Get VM Data Now--------------------- - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "RUNNING VMs" -ForegroundColor Green ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - $running = Get-VM | where {$_.state -eq 'running'} | sort Uptime | ` - select Name,State,CPUUsage,` - @{N="MemoryMB";E={$_.MemoryAssigned/1MB}},Uptime,Status ` - | ft -AutoSize - if($running -ne $null){ - $running - } - else{ - Write-Host "There are no running VMs - probably not a good thing."` - " Fix it." -ForegroundColor White -BackgroundColor Black - } - #--------------------------------------------------------------------- - Write-Host "`n" - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "NOT RUNNING VMs" -ForegroundColor Red ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - $notrunning = Get-VM | where {$_.state -ne 'running'} | ft -AutoSize - if($notrunning -ne $null){ - $notrunning - } - else{ - Write-Host "All VMs are currently running - HOORAY!" ` - -ForegroundColor White -BackgroundColor Black - } - #--------------END Get VM Data --------------------- - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - #--------------------------------------------------------------------- - } -} -<# -.Synopsis - A VM is comprised of multiple components. Each can reside in a different - location. This script will identify the location of all of those components -.DESCRIPTION - A VM is comprised of a few components besides just .vhd/.vhdx. This will - retrieve the location paths for the VM's configuration files, Snapshot Files, - and Smart Paging files. If on a standalone it will display this information - for all VMs on the standalone hyp. If a cluster is detected it will display - this information for all VMs found on each node. -.EXAMPLE - Get-VMLocationPathInfo - - This command will display the file paths for all VM components. -.OUTPUTS - Cluster detected. Executing cluster appropriate diagnostic... - ---------------------------------------------- - HypV1 - No VMs are present on this node. - ---------------------------------------------- - Hypv2 - - - VMName : 2008R2Clust - ComputerName : Hypv2 - State : Off - Path : \\sofs-csv\VMs\2008R2Clust - ConfigurationLocation : \\sofs-csv\VMs\2008R2Clust - SnapshotFileLocation : \\sofs-csv\VMs\2008R2Clust - SmartPagingFilePath : \\sofs-csv\VMs\2008R2Clust - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: - VMName - ComputerName - State - ConfigurationLocation - SnapshotFileLocation - SmartPagingFilePath -#> -#it will automatically detect standalone or cluster and will run the appropriate diagnostic -function Get-VMLocationPathInfo{ - Write-Host "This will not find any VMs if you are not running PowerShell as" ` - "admin!" -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #----------------------------------------------------------------------- - Foreach($node in $nodes){ - try{ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $VMInfo = get-vm -computername $node.name - $VMInfo | Select-Object VMName,ComputerName,State,Path,` - ConfigurationLocation,SnapshotFileLocation,SmartPagingFilePath - #Get-VMHardDiskDrive $VMinfo | Select-Object Name,PoolName,` - #Path,ComputerName,ID,VMName,VMId - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - #----------------------------------------------------------------------- - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #--------------------------------------------------------------------- - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $VMInfo = get-vm -computername $env:COMPUTERNAME - $VMInfo | Select-Object VMName,ComputerName,State,Path,` - ConfigurationLocation,SnapshotFileLocation,SmartPagingFilePath - #Get-VMHardDiskDrive $VMinfo | Select-Object Name,PoolName,` - #Path,ComputerName,ID,VMName,VMId - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - #--------------------------------------------------------------------- - } -} -<# -.Synopsis - Displays IntegrationServicesVersion and enabled integration services for all VMs -.DESCRIPTION - Gets the IntegrationServicesVersion and enabled integration services for all VMs. - Automatically detects if running on a standalone hyp or hyp cluster. - If standalone is detected it will display VM integration services information - for all VMs on the hyp. If a cluster is detected it will display VM integration - services information for all VMs found on each node. -.EXAMPLE - Get-IntegrationServicesCheck - - This command displays integration services information for all discovered VMs. -.OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - LinuxTest - no integration services installed - ---------------------------------------------- - LinuxTest3 - no integration services installed - ---------------------------------------------- - LinuxTest4 - no integration services installed - ---------------------------------------------- - PDC2 - version: 6.3.9600.16384 - - Name Enabled - ---- ------- - Time Synchronization True - Heartbeat True - Key-Value Pair Exchange True - Shutdown True - VSS True - Guest Service Interface False - ---------------------------------------------- - TestLinux2 - no integration services installed - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: - IntegrationServicesVersion - Enabled status for all integration services -#> -#it will automatically detect standalone or cluster and will run the appropriate diagnostic -function Get-IntegrationServicesCheck{ - Write-Host "This will not find any VMs if you are not running PowerShell as admin!" ` - -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #-------------------------------------------------------------------------- - Foreach($node in $nodes){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $vms = Get-VM -ComputerName $node.name | Select-Object ` - -ExpandProperty Name - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - foreach ($vm in $vms){ - $version = get-vm -ComputerName $node.name -Name $vm| ` - Select-Object -ExpandProperty integrationservicesversion - if($version -ne $null){ - Write-Host "$vm - version: $version" -ForegroundColor Magenta - Get-VMIntegrationService -ComputerName $node.name -VMName $vm | ` - select Name,Enabled | ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - else{ - Write-Host "$vm - no integration services installed" ` - -ForegroundColor Gray - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - } - - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - #----------------------------------------------------------------------- - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #--------------------------------------------------------------------- - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $vms = Get-VM | Select-Object -ExpandProperty Name - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - foreach ($vm in $vms){ - $version = get-vm -Name $vm| Select-Object ` - -ExpandProperty integrationservicesversion - if($version -ne $null){ - Write-Host "$vm - version: $version" ` - -ForegroundColor Magenta - Get-VMIntegrationService -VMName $vm | select Name,Enabled | ` - ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - else{ - Write-Host "$vm - no integration services installed" ` - -ForegroundColor Gray - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - } - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - #--------------------------------------------------------------------- - } -} -<# -.Synopsis - For each VM detected every associated VHD/VHDX is identified and several pieces of - VHD/VHDX information is displayed -.DESCRIPTION - Identifies all VHDs/VHDXs associated with each VM detected. For each VHD/VHDX it - pulls several pieces of information and displays to user. It then - sums the current VHD/VHDX disk usage and the POTENTIAL VHD/VHDX disk usage - dependent on whether the VHDs/VHDXs are fixed are dynamic. -.EXAMPLE - Get-VMAllVHDs - - Displays information for each VHD for every VM discovered -.OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - 2008R2Clust2 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx - ---------------------------------------------- - Web1 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx - ---------------------------------------------- - VMs are currently utilizing: 48 GB - VMs could POTENTIALLY Utilize: 180 GB - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM VHD information for all detected Hyp nodes: - VhdType - Size(GB) - MaxSize(GB) - Path - Total current disk usage - Total POTENTIAL disk usage -#> -function Get-VMAllVHDs{ - Write-Host "This will not find any VMs if you are not running PowerShell as "` - "admin!" -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - - [int]$currentStorageUse = $null - [int]$potentialStorageUse = $null - [int]$currentS = $null - [int]$potentialS = $null - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #------------------------------------------------------------------------ - Foreach($node in $nodes){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $VMs = Get-VM -ComputerName $node.name - foreach($VM in $VMs ){ - #---------for output------------- - Write-Host $vm.VMName -ForegroundColor White ` - -BackgroundColor Black - Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` - ft vhdtype,@{label=’Size(GB)’;` - expression={$_.filesize/1gb –as [int]}},` - @{label=’MaxSize(GB)’;expression={$_.size/1gb –as [int]}},` - path -AutoSize - #------END for output------------ - - #------for storage calc---------- - $cs = $null - $cs = Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` - Select-Object -ExpandProperty Filesize - #account for multiple vhds - $cs2 = $null - foreach($drive in $cs ){ - $cs2 = $cs2 + $drive - } - $ps = $null - $ps = Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` - Select-Object -ExpandProperty Size - #account for multiple vhds - $ps2 = $null - foreach($drive in $ps ){ - $ps2 = $ps2 + $drive - } - #math time - $cs3 = $null - $ps3 = $null - [int64]$cs3 = [convert]::ToInt64($cs2, 10) - [int64]$ps3 = [convert]::ToInt64($ps2, 10) - $cs3 = $cs3/1gb - $ps3 = $ps3/1gb - $currentS = $currentS + $cs3 - $potentialS = $potentialS + $ps3 - #------END for storage calc------ - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - #------------------------------------------------------------------------ - $currentStorageUse = $currentS - $potentialStorageUse = $potentialS - Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "VMs could POTENTIALLY Utilize: " $potentialStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #------------------------------------------------------------------------ - } - - else{ - #------------------------------------------------------------------------ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - #--------------------------------------------------------------------- - $VMs=Get-VM - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - foreach($VM in $VMs ){ - #---------for output------------- - Write-Host $vm.VMName -ForegroundColor White -BackgroundColor Black - Get-VHD -VMId $VM.VMId | ft vhdtype,@{label=’Size(GB)’; ` - expression={$_.filesize/1gb –as [int]}},@{label=’MaxSize(GB)’; ` - expression={$_.size/1gb –as [int]}},path -AutoSize - #------END for output------------ - - #------for storage calc---------- - $cs = $null - $cs = Get-VHD -VMId $VM.VMId | Select-Object -ExpandProperty Filesize - #account for multiple vhds - $cs2 = $null - foreach($drive in $cs ){ - $cs2 = $cs2 + $drive - } - $ps = $null - $ps = Get-VHD -VMId $VM.VMId | Select-Object -ExpandProperty Size - #account for multiple vhds - $ps2 = $null - foreach($drive in $ps ){ - $ps2 = $ps2 + $drive - } - #math time - $cs3 = $null - $ps3 = $null - [int64]$cs3 = [convert]::ToInt64($cs2, 10) - [int64]$ps3 = [convert]::ToInt64($ps2, 10) - $cs3 = $cs3/1gb - $ps3 = $ps3/1gb - $currentS = $currentS + $cs3 - $potentialS = $potentialS + $ps3 - #------END for storage calc------ - Write-Host "----------------------------------------------" -ForegroundColor Gray - } - #--------------------------------------------------------------------- - $currentStorageUse = $currentS - $potentialStorageUse = $potentialS - Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "VMs could POTENTIALLY Utilize: " $potentialStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------------------------------------------------------------- - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - } -} -<# -.Synopsis - For each VM detected every associated VHD/VHDX is checked to determine - if the VHD/VHDX is shared or not -.DESCRIPTION - Identifies all VHDs/VHDXs associated with each VM detected. For each VHD/VHDX it - pulls several pieces of information to display to user. If - SupportPersistentReservations is true, the VHD/VHDX is shared. -.EXAMPLE - Get-SharedVHDs - - Displays SupportPersistentReservations information for each VHD for every VM - discovered. If SupportPersistentReservations is true, the VHD is shared -.OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - 2008R2Clust2 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx - ---------------------------------------------- - Web1 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx - ---------------------------------------------- - VMs are currently utilizing: 48 GB - VMs could POTENTIALLY Utilize: 180 GB - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM VHD information for all detected Hyp nodes: - VMName - SupportPersistentReservations - Path -#> -function Get-SharedVHDs{ - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------------------------------------------------------------- - Foreach($node in $nodes){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - get-vm -ComputerName $node.name | Get-VMHardDiskDrive | select VMName,` - supportpersistentreservations, path | ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - #--------------------------------------------------------------------- - - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - $quickCheck = Get-VM | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - #--------------------------------------------------------------------- - get-vm | Get-VMHardDiskDrive | select VMName,` - supportpersistentreservations, path | ft -AutoSize - #--------------------------------------------------------------------- - - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - - } -} -<# -.Synopsis - Determines the current resource allocation health of Hyper-V Server or Hyper-V Cluster -.DESCRIPTION - For single Hyper-V instances this function will pull available - CPU and Memory physical resources. It will then tally all VM CPU and memory - allocations and contrast that info with available physical resources - - A cpu ratio higher than 4:1 (vCPU:Logical Processors) will be flagged as bad - A static memory higher than 1:1 will be flagged as bad - There is no best practice published around dynamic maximum memory so the function - will only advise a warning if max memory is higher than available physical memory. - - The same functionality is supported for clustered Hyper-V instances. - The function will poll each node in the cluster and provide info on each node. - The cluster function will also calculate the simulation loss of one node to determine - if VMs could survive and start with one node down. - - Available storage space will also be calculated. For clusters CSV locations will be - checked. For standalone Hyps any drive larger than 10GB and not C: will be checked. - In keeping with best practices anything with less than 20% free space will fail the - health check. -.EXAMPLE - Test-HyperVAllocation - - If executed on a standalone Hyper-V instance it will retrieve CPU/RAM physical resources - If exectured on a Hyper-V cluster it will retrieve CPU/RAM physical resrouces for - all nodes in the cluster and comapares those available resources to resources assigned - to VMs on each Hyper-V instance. -.OUTPUTS - ----------------------------- - SystemName: 80167-hyp2 - ----------------------------- - Cores: 24 - Logical Processors: 48 - Total Memory: 256 GB - Free Memory: 248 GB - Number of VMs: 1 - Number of VM Procs: 2 - ----------------------------- - Memory resources are still available: 97 % free - ----------------------------- - Virtual Processors are not overprovisioned 1 : 1 - ----------------------------- - Total Startup memory required for Dynamic VMs: 0 GB - Total Static memory required for Static VMs: 29 GB - ----------------------------- - Total minimum RAM (Startup+Static) required: 29 GB - Minimum RAM: 29 GB does not exceed available RAM: 256 GB - ----------------------------- - VMs would survive a one node failure - Total VM RAM minumum: 56 GB - Total Cluster RAM available with one node down: 256 GB - ----------------------------- - Storage Allocation Information - ----------------------------- - C:\ClusterStorage\Volume2 has the recommended 20% free space. - Free Space: 100 GB - Percent Free: 99.87756 - ----------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - You can change the CPU ratio cutoff from 4:1 to say 6:1 or 8:1 by editing the - Highlighted section below to suit your requirements -.FUNCTIONALITY - Get the following information for each Hyper-V instance found - System Name - Logical Processors - Total Memory - Free Memory - Number of VMs - Number of VM Procs - CPU provisioning status - Memory provisioning status - Free space status -#> -function Test-HyperVAllocation{ - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - foreach($node in $nodes){ - if(Test-Connection -ComputerName $node){ - - } - else{ - Write-Host "Not all nodes could be reached - please address $node" -ForegroundColor Red - return - } - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - - if($nodes -ne $null){ - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." -ForegroundColor Yellow -BackgroundColor Black - $totalClusterRAM = $null - $totalVMClusterRAM = $null - $nodeCount = 0 - #######################CLUSTER DIAG######################## - #we are definitely dealing with a cluster - execute code for cluster - #--------------------------------------------------------------------- - Foreach($node in $nodes){ - $w32ProcInfo = $null - $w32OSInfo = $null - $name = $null - $numCores = $null - $numLogicProcs = $null - $totalNumCores = $null - $totalNumLogicProcs =$null - [double]$totalMemory = $null - [double]$freeMemory = $null - $nodeCount += 1 - #--------------------------------------------------------------------- - #get WMI data loaded up - #-------------------------------------------------------------------- - try{ - $w32ProcInfo = Get-WmiObject -Namespace "root\cimv2" -Class win32_processor -Impersonation 3 -ComputerName $node - $w32OSInfo = Get-WmiObject -Namespace "root\cimv2" -Class Win32_OperatingSystem -Impersonation 3 -ComputerName $node - } - catch{ - Write-Host "An error was encountered getting WMI info from $node" -ForegroundColor Red - Write-Error $_ - Return - } - #-------------------------------------------------------------------- - #load specific WMI data into variables - #-------------------------------------------------------------------- - $name = $node - $numCores = $w32ProcInfo.numberOfCores - foreach($core in $numCores){ - $totalNumCores += $core - } - $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors - foreach($proc in $numLogicProcs){ - $totalNumLogicProcs += $proc - } - $totalMemory = [math]::Round($w32OSInfo.TotalVisibleMemorySize /1MB, 0) - $freeMemory = [math]::Round($w32OSInfo.FreePhysicalMemory /1MB, 0) - $totalClusterRAM += $totalMemory - #-------------------------------------------------------------------- - #-------------------------------------------------------------------- - #load VM data and count number of VMs and VMs processors - #-------------------------------------------------------------------- - $vms = $null - $vmCount = $null - $vmProcCount = $null - $totalVMProcCount = $null - try{ - $vms = Get-VM -ComputerName $node - $vmCount = $vms | measure | Select-Object -ExpandProperty count - $vmProcCount = $vms | Get-VMProcessor | Select-Object -ExpandProperty count - } - catch{ - Write-Host "An error was encountered getting VM info from $node" -ForegroundColor Red - Write-Error $_ - Return - } - - foreach($proc in $vmProcCount){ - $totalVMProcCount += $proc - } - #-------------------------------------------------------------------- - #null all counts to permit multiple script runs - #-------------------------------------------------------------------- - $memorystartup = 0 - $MemoryMaximum = 0 - $totalstartupmem = 0 - $totalmaxmem = 0 - $static = 0 - $staticmemory = 0 - #-------------------------------------------------------------------- - #calculate memory usage dynamic/static for each VM to generate totals - #-------------------------------------------------------------------- - foreach ($vm in $vms) { - if ((Get-VMMemory -ComputerName $node -vmname $vm.Name).DynamicMemoryEnabled -eq "True") { - $memoryStartup = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup /1GB, 0) - $memoryMaximum = [math]::Round(($VM | select-object MemoryMaximum).memorymaximum /1GB, 0) - $totalstartupmem += $memoryStartup - $totalmaxmem += $memoryMaximum - } - else { - $static = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) - $staticmemory += $static - } - } - $totalramrequired=$totalstartupmem + $staticmemory - $totalVMClusterRAM += $totalramrequired - #account for no static and no dynamic situations - if($totalstartupmem -eq $null){ - $totalstartupmem = 0 - } - if($staticmemory -eq $null){ - $staticmemory = 0 - } - #-------------------------------------------------------------------- - #output basic information about server - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "SystemName:" $name - Write-Host "-----------------------------" - Write-Host "Cores:" $totalNumCores - Write-Host "Logical Processors:" $totalNumLogicProcs - Write-Host "Total Memory:" $totalMemory GB - Write-Host "Free Memory:" $freeMemory GB - Write-Host "Number of VMs:" $vmCount - Write-Host "Number of VM Procs:" $totalVMProcCount - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #current memory usage status: - #-------------------------------------------------------------------- - #total memory vs free memory - less than 10% free is considered bad - $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100 - if($memPercent -lt 10){ - Write-Host "This system is low on memory resources: $memPercent % free" -ForegroundColor Red - } - else{ - Write-Host "Memory resources are still available: $memPercent % free" -ForegroundColor Green - } - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #cpu ratio output - #-------------------------------------------------------------------- - #$vmProcCount = 49 - if($totalVMProcCount -gt $totalNumLogicProcs){ - $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount) - $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs) - #--------DEFAULT IS 4:1 which is 1/4 = .25------------------------ - if($cpuRatio -lt .25){ - #adjust above this line to achieve desired ratio------------------ - $procRatio +=1 - Write-Host "Overprovisioned on Virtual processors." $procRatio ": 1" -ForegroundColor Red - } - else{ - Write-Host "Virtual Processors not overprovisioned" $procRatio ": 1" -ForegroundColor Green - } - } - else{ - Write-Host "Virtual Processors are not overprovisioned 1 : 1" -ForegroundColor Green - } - #-------------------------------------------------------------------- - #memory ratio information - #-------------------------------------------------------------------- - write-host "-----------------------------" - write-host "Total Startup memory required for Dynamic VMs: $totalstartupmem GB " - write-host "Total Static memory required for Static VMs: $staticmemory GB " - write-host "-----------------------------" - write-host "Total minimum RAM (Startup+Static) required: $totalramrequired GB " - if($totalramrequired -lt $totalMemory){ - Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Minimum RAM: $totalramrequired GB exceeds available RAM: $totalMemory GB" -ForegroundColor Red - } - write-host "-----------------------------" - if($totalmaxmem -ne 0){ - write-host "Total *Potential* Maximum memory for Dynamic VMs: $totalmaxmem GB" - if($totalmaxmem -lt $totalMemory){ - Write-Host "Maximum potential RAM: $totalmaxmem GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Maximum potential RAM: $totalmaxmem GB exceeds available RAM: $totalMemory GB" -ForegroundColor Yellow - } - } - #-------------------------------------------------------------------- - } - #calculating a node loss and its impact - $x = $totalClusterRAM / $nodeCount - $clusterNodeDownUseable = $totalClusterRAM - $x - if($totalVMClusterRAM -gt $clusterNodeDownUseable){ - Write-Host "VMs would NOT survive a one node failure" -ForegroundColor Red - Write-Host "Total VM RAM minumum: $totalVMClusterRAM GB - Total Cluster RAM available with one node down: $clusterNodeDownUseable GB" -ForegroundColor Cyan - } - else{ - Write-Host "VMs would survive a one node failure" -ForegroundColor Green - Write-Host "Total VM RAM minumum: $totalVMClusterRAM GB - Total Cluster RAM available with one node down: $clusterNodeDownUseable GB" -ForegroundColor Cyan - } - #-------------------------------------------------------------------- - #CSV Storage Space checks - we will check CSV locations only for clustered Hyps - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "Storage Allocation Information" - Write-Host "-----------------------------" - try{ - $clusterName = "." - $clusterSharedVolume = Get-ClusterSharedVolume -Cluster $clusterName ` - -ErrorAction SilentlyContinue - if ($clusterSharedVolume -eq $null){ - Write-Host "No CSVs discovered - no storage information pulled" ` - -ForegroundColor Yellow - } - else{ - foreach ($volume in $clusterSharedVolume){ - $volumeowner = $volume.OwnerNode.Name - $csvVolume = $volume.SharedVolumeInfo.Partition.Name - $cimSession = New-CimSession -ComputerName $volumeowner - $volumeInfo = Get-Disk -CimSession $cimSession | Get-Partition | ` - Select DiskNumber, @{Name="Volume"; ` - Expression={Get-Volume -Partition $_ | ` - Select -ExpandProperty ObjectId} - } - $csvdisknumber = ($volumeinfo | where ` - { $_.Volume -eq $csvVolume}).Disknumber - $diskName = $volume.SharedVolumeInfo.FriendlyVolumeName - $percentFree = $volume.SharedVolumeInfo.Partition.PercentFree - $spaceFree = [int]($volume.SharedVolumeInfo.Partition.Freespace/1GB) - if($percentFree -lt 20){ - Write-Host $diskName "is below the recommended 20% free space." -ForegroundColor Red - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Red - Write-Host "Percent Free: $percentFree" -ForegroundColor Red - Write-Host "-----------------------------" - } - else{ - Write-Host $diskName "has the recommended 20% free space." -ForegroundColor Green - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Gray - Write-Host "Percent Free: $percentFree" -ForegroundColor Gray - Write-Host "-----------------------------" - } - } - } - - } - catch{ - Write-Host "ERROR - An issue was encountered getting CSVs spacing information:" ` - -ForegroundColor Red - } - #######################END CLUSTER DIAG######################## - } - else{ - #standalone server - execute code for standalone server - #######################STANDALONE DIAG######################## - Write-Host "Standalone server detected. Executing standalone diagnostic..." -ForegroundColor Yellow -BackgroundColor Black - #--------------------------------------------------------------------- - #get WMI data loaded up - #-------------------------------------------------------------------- - try{ - $w32ProcInfo = Get-WmiObject -class win32_processor - $w32OSInfo = Get-WMIObject -class Win32_OperatingSystem - } - catch{ - Write-Host "An error was encountered getting WMI info from $node" -ForegroundColor Red - Write-Error $_ - Return - } - #-------------------------------------------------------------------- - #load specific WMI data into variables - #-------------------------------------------------------------------- - $name = $w32ProcInfo.systemname - $numCores = $w32ProcInfo.numberOfCores - foreach($core in $numCores){ - $totalNumCores += $core - } - $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors - foreach($proc in $numLogicProcs){ - $totalNumLogicProcs += $proc - } - $totalMemory = [math]::round($w32OSInfo.TotalVisibleMemorySize /1MB, 0) - $freeMemory = [math]::round($w32OSInfo.FreePhysicalMemory /1MB, 0) - #-------------------------------------------------------------------- - #load VM data and count number of VMs and VMs processors - #-------------------------------------------------------------------- - try{ - $vms = Get-VM - $vmCount = $vms | measure | Select-Object -ExpandProperty count - $vmProcCount = $vms | Get-VMProcessor | Select-Object -ExpandProperty count - } - catch{ - Write-Host "An error was encountered getting VM info" -ForegroundColor Red - Write-Error $_ - Return - } - - foreach($proc in $vmProcCount){ - $totalVMProcCount += $proc - } - #-------------------------------------------------------------------- - #null all counts to permit multiple script runs - #-------------------------------------------------------------------- - $memorystartup = 0 - $MemoryMaximum = 0 - $totalstartupmem = 0 - $totalmaxmem = 0 - $static = 0 - $staticmemory = 0 - #-------------------------------------------------------------------- - #calculate memory usage dynamic/static for each VM to generate totals - #-------------------------------------------------------------------- - foreach ($vm in $vms) { - if ((Get-VMMemory -vmname $vm.Name).DynamicMemoryEnabled -eq "True") { - $memorystartup = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) - $memoryMaximum = [math]::Round(($VM | select-object MemoryMaximum).memorymaximum / 1GB, 0) - - $totalstartupmem += $memoryStartup - $totalmaxmem += $memoryMaximum - } - else { - $static = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) - $staticmemory += $static - } - } - $totalramrequired=$totalstartupmem + $staticmemory - #account for no static and no dynamic situations - if($totalstartupmem -eq $null){ - $totalstartupmem = 0 - } - if($staticmemory -eq $null){ - $staticmemory = 0 - } - #-------------------------------------------------------------------- - #output basic information about server - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "SystemName:" $name - Write-Host "-----------------------------" - Write-Host "Cores:" $totalNumCores - Write-Host "Logical Processors:" $totalNumLogicProcs - Write-Host "Total Memory:" $totalMemory GB - Write-Host "Free Memory:" $freeMemory GB - Write-Host "Number of VMs:" $vmCount - Write-Host "Number of VM Procs:" $totalVMProcCount - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #current memory usage status: - #-------------------------------------------------------------------- - #total memory vs free memory - less than 10% free is considered bad - $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100 - if($memPercent -lt 10){ - Write-Host "This system is low on memory resources: $memPercent % free" -ForegroundColor Red - } - else{ - Write-Host "Memory resources are still available: $memPercent % free" -ForegroundColor Green - } - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #cpu ratio output - #-------------------------------------------------------------------- - #$vmProcCount = 49 - if($totalVMProcCount -gt $totalNumLogicProcs){ - $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount) - $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs) - #$procRatio2 = [math]::round($procRatio / $cpuRatio) - #------------HERE YOU CAN CHANGE CPU RATIO TO DESIRED RATIO------- - #--------DEFAULT IS 4:1 which is 1/4 = .25------------------------ - if($cpuRatio -lt .25){ - #adjust above this line to achieve desired ratio------------------ - $procRatio +=1 - Write-Host "Overprovisioned on Virtual processors." $procRatio ": 1" -ForegroundColor Red - } - else{ - Write-Host "Virtual Processors not overprovisioned" $procRatio ": 1" -ForegroundColor Green - } - } - else{ - Write-Host "Virtual Processors are not overprovisioned 1 : 1" -ForegroundColor Green - } - #-------------------------------------------------------------------- - #memory ratio information - #-------------------------------------------------------------------- - write-host "-----------------------------" - write-host "Total Startup memory required for Dynamic VMs: $totalstartupmem GB " - write-host "Total Static memory required for Static VMs: $staticmemory GB " - write-host "-----------------------------" - write-host "Total minimum RAM (Startup+Static) required: $totalramrequired GB " - if($totalramrequired -lt $totalMemory){ - Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Minimum RAM: $totalramrequired GB exceeds available RAM: $totalMemory GB" -ForegroundColor Red - } - write-host "-----------------------------" - if($totalmaxmem -ne 0){ - write-host "Total *Potential* Maximum memory for Dynamic VMs: $totalmaxmem GB" - if($totalmaxmem -lt $totalMemory){ - Write-Host "Maximum potential RAM: $totalmaxmem GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Maximum potential RAM: $totalmaxmem GB exceeds available RAM: $totalMemory GB" -ForegroundColor Yellow - } - } - #-------------------------------------------------------------------- - #Storage Space checks - we will check all drives greater than 10GB that are no C: - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "Storage Allocation Information" - Write-Host "-----------------------------" - $drives = Get-WmiObject win32_logicaldisk -ErrorAction SilentlyContinue | Where-Object {$_.DeviceID -ne "C:"} - if($drives -ne $null){ - foreach($drive in $drives){ - $totalSize = [int]($drive.Size/1GB) - if($totalSize -gt 10){ - $driveLetter = $drive.DeviceID - $spaceFree = [int]($drive.Freespace/1GB) - $percentFree = [math]::round(($spaceFree / $totalSize) * 100) - if($percentFree -lt 20){ - Write-Host $driveLetter "is below the recommended 20% free space." -ForegroundColor Red - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Red - Write-Host "Percent Free: $percentFree" -ForegroundColor Red - Write-Host "-----------------------------" - } - else{ - Write-Host $driveLetter "has the recommended 20% free space." -ForegroundColor Green - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Gray - Write-Host "Percent Free: $percentFree" -ForegroundColor Gray - Write-Host "-----------------------------" - } - } - } - } - else{ - Write-Host "No additional storage other than OS drive deteceted" ` - -ForegroundColor Yellow - } - #######################STANDALONE DIAG######################## - #-------------------------------------------------------------------- - } -} -<# -.Synopsis - Resolves CSV to a physicalDisk drive -.DESCRIPTION - Discovers all cluster shared volumes associated with the specificed cluster - Resolves all cluster shared volumes to physical drives and pulls usefull - information about the characteristcs of the associated physical drive -.EXAMPLE - Get-CSVtoPhysicalDiskMapping - - This command retrieves all cluster shared volumes and pulls information - related to the physical disk associated with each CSV. Since no cluster name - is specified this command resolves to a locally available cluster (".") -.EXAMPLE - Get-CSVtoPhysicalDiskMappying -clusterName "Clus1.domain.local" - - This command retrieves all cluster shared volumes and pulls information related - to the physical disk associated with the CSVs that are associated with the - Clus1.domain.local cluster. -.OUTPUTS - #CSVName : Cluster Disk 1 - #CSVPartitionNumber : 2 - #Size (GB) : 1500 - #CSVOwnerNode : node1 - #FreeSpace (GB) : 697 - #CSVVolumePath : C:\ClusterStorage\Volume1 - #CSVPhysicalDiskNumber : 3 - #Perecent Free : 46.49729 -.NOTES - Adapted from code written by Ravikanth Chaganti http://www.ravichaganti.com - Enhanced by: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following information for each CSV in the cluster: - CSV Name - Total Size of associated physical disk - CSV Volume Path - Percent free of physical disk - VERY useful - CSV Owner Node - CSV Partition Number - Freespace in (GB) -#> -function Get-CSVtoPhysicalDiskMapping{ - [cmdletbinding()] - Param - ( - #clusterName should be the FQDN of your cluster, if not specified it will - [Parameter(Mandatory = $false, - ValueFromPipeline = $false, - ValueFromPipelineByPropertyName = $true, - Position = 0)] - [string] - $clusterName = "." - ) - try{ - $clusterSharedVolume = Get-ClusterSharedVolume -Cluster $clusterName ` - -ErrorAction SilentlyContinue - if ($clusterSharedVolume -eq $null){ - Write-Host "No CSVs discovered - script has completed" ` - -ForegroundColor Yellow - } - else{ - foreach ($volume in $clusterSharedVolume) { - $volumeowner = $volume.OwnerNode.Name - $csvVolume = $volume.SharedVolumeInfo.Partition.Name - $cimSession = New-CimSession -ComputerName $volumeowner - $volumeInfo = Get-Disk -CimSession $cimSession | Get-Partition | ` - Select DiskNumber, @{Name="Volume"; ` - Expression={Get-Volume -Partition $_ | ` - Select -ExpandProperty ObjectId} - } - $csvdisknumber = ($volumeinfo | where ` - { $_.Volume -eq $csvVolume}).Disknumber - $csvtophysicaldisk = New-Object -TypeName PSObject -Property @{ - "CSVName" = $volume.Name - "Size (GB)" = [int]($volume.SharedVolumeInfo.Partition.Size/1GB) - "CSVVolumePath" = $volume.SharedVolumeInfo.FriendlyVolumeName - "Perecent Free" = $volume.SharedVolumeInfo.Partition.PercentFree - "CSVOwnerNode"= $volumeowner - "CSVPhysicalDiskNumber" = $csvdisknumber - "CSVPartitionNumber" = $volume.SharedVolumeInfo.PartitionNumber - "FreeSpace (GB)" = [int]($volume.SharedVolumeInfo.Partition.Freespace/1GB) - } - $csvtophysicaldisk - } - } - } - catch{ - Write-Host "ERROR - An issue was encountered getting physical disks of CSVs:" ` - -ForegroundColor Red - Write-Error $_ - } -} -<# -.Synopsis - Scans specified path and gets total size as well as top 10 largest files -.DESCRIPTION - Recursively scans all files in the specified path. It then gives a total - size in GB for all files found under the specified location as well as - the top 10 largest files discovered. The length of scan completion is - impacted by the size of the path specified as well as the number of files -.EXAMPLE - Get-FileSizes -path C:\temp - - This command recursively scans the specified path and will tally the total - size of all discovered files as well as the top 10 largest files. -.OUTPUTS - Scan results for: c:\ - ---------------------------------------------- - Total size of all files: 175 GB. - ---------------------------------------------- - Top 10 Largest Files found: - - Directory Name Length - --------- ---- ------ - C:\rs-pkgs ManagementPC.vhdx 28.19 - C:\rs-pkgs CentOS-7-x86_64-Everything-1503-01.iso 7.07 - C:\ hiberfil.sys 6.38 - C:\rs-pkgs en_windows_10_multiple_editions_x64_dvd_6846432.iso 3.8 - C:\rs-pkgs UbuntuServer14.vhdx 3.6 - C:\GOG Games\The Witcher 3 Wild Hunt\content\content0 texture.cache 3.24 - C:\GOG Games\The Witcher 3 Wild Hunt\content\content4\bundles movies.bundle 3.23 - C:\Program Files (x86)\StarCraft II\Campaigns\Liberty.SC2Campaign Base.SC2Assets 3.16 - C:\Program Files (x86)\StarCraft II\Mods\Liberty.SC2Mod Base.SC2Assets 2.42 - C:\ pagefile.sys 2.38 - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following information for the specified path: - Total size of all files found under the path - Top 10 largest files discovered -#> -function Get-FileSizes{ - [cmdletbinding()] - Param ( - #directory path that you wish to scan - [Parameter(Mandatory = $true, - HelpMessage = "Please enter a path (Ex: C:\ClusterStorage\Volume1)", - ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true, Position = 0) - ] - [string]$path - ) - - Write-Host "Note - depending on how many files are in the path you specified "` - "this scan can take some time. Patience please..." -ForegroundColor Gray - #test path and then load location - try{ - $check = Test-Path $path - if($check -eq $true){ - $files = Get-ChildItem -Path $path -Recurse -Force ` - -ErrorAction SilentlyContinue - } - else{ - Write-Host "The path you specified is not valid" -ForegroundColor Red - return - } - } - catch{ - Write-Error $_ - } - [double]$intSize = 0 - try{ - #get total size of all files - foreach ($objFile in $files){ - $i++ - $intSize = $intSize + $objFile.Length - Write-Progress -activity "Adding File Sizes" -status "Percent added: " ` - -PercentComplete (($i / $files.length) * 100) - } - $intSize = [math]::round($intSize / 1GB, 0) - #generate output - Write-Host "Scan results for: $path" -ForegroundColor Cyan - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "Total size of all files: $intSize GB." ` - -ForegroundColor Magenta - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "Top 10 Largest Files found:" -ForegroundColor Cyan - $files | select Directory,Name,` - @{Label=”Length”;Expression={[math]::round($_.Length/1GB, 2)}} | ` - sort Length -Descending| select -First 10 | ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - catch{ - Write-Error $_ - } - -} -#################################################################################### -#----------------------------END Diagnostic FUNCTIONS------------------------------- -#################################################################################### -#lets autorun the choice menu now -Diag-V \ No newline at end of file diff --git a/Diag-V.psd1 b/Diag-V.psd1 new file mode 100644 index 0000000..0aa96df --- /dev/null +++ b/Diag-V.psd1 @@ -0,0 +1,103 @@ +# +# Module manifest for module 'Diag-V' +# +# Generated by: Jake Morrison +# +# Generated on: 1/24/2012 +# + +@{ + + # Script module or binary module file associated with this manifest + RootModule = 'Diag-V.psm1' + + # Version number of this module. + ModuleVersion = '2.0' + + # ID used to uniquely identify this module + GUID = 'd0a9150d-b6a4-4b17-a325-e3a24fed0aa9' + + # Author of this module + Author = 'Jake Morrison' + + # Company or vendor of this module + CompanyName = 'Tech Thoughts' + + # Copyright statement for this module + Copyright = '(c) 2018 Jacob Morrison. All rights reserved.' + + # Description of the functionality provided by this module + # Description = '' + + # Minimum version of the Windows PowerShell engine required by this module + # PowerShellVersion = '' + + # Name of the Windows PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the Windows PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of the .NET Framework required by this module + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module + # CLRVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module + FunctionsToExport = @( + 'Get-VMStatus', + 'Get-VMInfo', + 'Get-VMReplicationStatus', + 'Get-IntegrationServicesCheck', + 'Get-BINSpaceInfo', + 'Get-VMAllVHDs', + 'Show-DiagVMenu' + ) + + # Cmdlets to export from this module + #CmdletsToExport = '*' + + # Variables to export from this module + #VariablesToExport = '*' + + # Aliases to export from this module + #AliasesToExport = '*' + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess + # PrivateData = '' + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + + } \ No newline at end of file diff --git a/Diag-V.psm1 b/Diag-V.psm1 new file mode 100644 index 0000000..a0801df --- /dev/null +++ b/Diag-V.psm1 @@ -0,0 +1,1804 @@ +#region supportingFunctions + +<# +.Synopsis + Evaluates if local device is a member of a cluster or a standalone server +.DESCRIPTION + Evaluates several factors to determine if device is a member of a cluster or acting as a standalone server. The cluster service is evaluated, and if present the cluster nodes will be tested to determine if the local device is a member. If the cluster service is not running the cluster registry location is evaluated to determine if the server's cluster membership status. +.EXAMPLE + Test-IsACluster + + Returns boolean if local device is part of a cluster +.OUTPUTS + Boolean value +.NOTES + Author: Jake Morrison + http://techthoughts.info + + The design of this function intends the function to be run on the device that is being evaluated +#> +function Test-IsACluster { + [CmdletBinding()] + param () + #assume device is not a cluster + [bool]$clusterEval = $false + $nodes = $null + $clusterCheck = $null + $clusterNodeNames = $null + try { + $hostName = $env:COMPUTERNAME + Write-Verbose -Message "HostName is: $hostName" + Write-Verbose -Message "Verifying presence of cluster service..." + $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue + if ($clusterCheck -ne $null) { + Write-Verbose -Message "Cluster Service found." + Write-Verbose -Message "Checking cluster service status..." + $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status + if ($clusterServiceStatus -eq "Running") { + Write-Verbose -Message "Cluster serivce running." + Write-Verbose -Message "Evaluating cluster nodes..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name + if ($nodes -ne $null) { + foreach ($node in $nodes) { + if ($hostName -eq $node) { + $clusterEval = $true + Write-Verbose -Message "Hostname was found among cluster nodes." + } + } + Write-Verbose -Message "Cluster node evaulation complete." + } + } + else { + Write-Verbose -Message "Cluster service is not running. Cluster cmdlets not possible. Switching to registry evaluation..." + $clusterRegistryPath = "HKLM:\SYSTEM\CurrentControlSet\Services\ClusSvc\Parameters" + $clusterNodeNames = Get-ItemProperty -Path $clusterRegistryPath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty NodeNames -ErrorAction Stop + if ($clusterNodeNames -ne $null) { + if ($clusterNodeNames -like "*$hostName*") { + $clusterEval = $true + Write-Verbose -Message "Hostname was found in cluster registy settings" + } + else { + Write-Verbose -Message "Hostname was not found in cluster registry settings." + } + } + } + } + else { + Write-Verbose -Message "No cluster service was found." + } + } + catch { + Write-Verbose -Message "There was an error determining if this server is part of a cluster." + Write-Error $_ + } + return $clusterEval +} +<# +.Synopsis + Tests if PowerShell Session is running as Admin +.DESCRIPTION + Evaluates if current PowerShell session is running under the context of an Administrator +.EXAMPLE + Test-RunningAsAdmin + + This will verify if the current PowerShell session is running under the context of an Administrator +.OUTPUTS + Boolean value +.NOTES + Author: Jake Morrison + http://techthoughts.info +#> +function Test-RunningAsAdmin { + [CmdletBinding()] + Param() + $result = $false #assume the worst + try { + Write-Verbose -Message "Testing if current PS session is running as admin..." + $eval = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + if ($eval -eq $true) { + Write-Verbose -Message "PS Session is running as Administrator." + $result = $true + } + else { + Write-Verbose -Message "PS Session is NOT running as Administrator" + } + } + catch { + Write-Verbose -Message "Error encountering evaluating runas status of PS session" + Write-Error $_ + } + return $result +} +<# +.SYNOPSIS + Import-CimXml iterates through INSTANCE/PROPERTY data to find the desired information +.DESCRIPTION + Import-CimXml iterates through INSTANCE/PROPERTY data to find the desired information +.EXAMPLE + + +.OUTPUTS + Custom object return +.NOTES + Supporting function for Get-VMInfo +#> +filter Import-CimXml { + # Filter for parsing XML data + + # Create new XML object from input + $CimXml = [Xml]$_ + $CimObj = New-Object System.Management.Automation.PSObject + + # Iterate over the data and pull out just the value name and data for each entry + foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Name']")) { + $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE + } + + foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Data']")) { + $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE + #return $CimProperty.VALUE + } + + return $CimObj +} + +#endregion + +#region vmDiagnosticFunctions + +<# +.Synopsis + Name, State, CPUUsage, Memory usage, Uptime, and Status of all VMs on a cluster or standalone hyp +.DESCRIPTION + Gets the status of all discovered VMs. Automatically detects if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM status information for all VMs on the hyp. If a cluster is detected it will display VM status information for each node in the cluster. +.EXAMPLE + Get-VMStatus + + This command will automatically detect a standalone hyp or hyp cluster and will retrieve VM status information for all detected nodes. +.OUTPUTS + ---------------------------------------------- + RUNNING VMs + ---------------------------------------------- + HYP1 + VMs are present on this node, but none are currently running. + ---------------------------------------------- + HYP2 + No VMs are present on this node. + ---------------------------------------------- + + + ---------------------------------------------- + NOT RUNNING VMs + ---------------------------------------------- + HYP1 + + Name State CPUUsage MemoryMB Status IsClustered + ---- ----- -------- -------- ------ ----------- + PSHost-1 Off 0 0 Operating normally False + + + ---------------------------------------------- + HYP2 + No VMs are present on this node. + ---------------------------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info + it will automatically detect standalone or cluster and will run the appropriate diagnostic +.FUNCTIONALITY + Get the following VM information for all detected Hyp nodes: + Name + State + CPUUsage + Memory + Uptime + Status + IsClustered +#> +function Get-VMStatus { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Host "----------------------------------------------" -ForegroundColor Gray + Write-Host "RUNNING VMs" -ForegroundColor Green -BackgroundColor Black + Write-Host "----------------------------------------------" -ForegroundColor Gray + Write-Verbose "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + Foreach ($node in $nodes) { + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $running = Get-VM -ComputerName $node.name | ` + Where-Object {$_.state -eq 'running'} | Sort-Object Uptime | ` + Select-Object Name, State, CPUUsage, ` + @{N = "MemoryMB"; E = {$_.MemoryAssigned / 1MB}}, Uptime, Status, ` + IsClustered| Format-Table -AutoSize + if ($running -ne $null) { + $running + } + else { + Write-Host "VMs are present on this node, but none are currently running." ` + -ForegroundColor Yellow -BackgroundColor Black + } + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #--------------END Get VM Data --------------------- + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + } + Write-Host "`n" + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host "NOT RUNNING VMs" -ForegroundColor Red ` + -BackgroundColor Black + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Foreach ($node in $nodes) { + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + Write-Host $node.name -ForegroundColor White ` + -BackgroundColor Black + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $notrunning = Get-VM -ComputerName $node.name | ` + Where-Object {$_.state -ne 'running'} | ` + Select-Object Name, State, CPUUsage, ` + @{N = "MemoryMB"; E = {$_.MemoryAssigned / 1MB}}, Status, ` + IsClustered| Format-Table -AutoSize | Format-Table -AutoSize + if ($notrunning -ne $null) { + $notrunning + } + else { + Write-Host "All VMs on this node report as Running." ` + -ForegroundColor White -BackgroundColor Black + } + } + else { + Write-Host "No VMs are present on this node." ` + -ForegroundColor White -BackgroundColor Black + } + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #--------------END Get VM Data --------------------- + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + } + #------------------------------------------------------------------------ + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + + }#cluster eval + else { + #standalone server - execute code for standalone server + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host "RUNNING VMs" -ForegroundColor Green ` + -BackgroundColor Black + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + $running = Get-VM | Where-Object {$_.state -eq 'running'} | Sort-Object Uptime | ` + Select-Object Name, State, CPUUsage, ` + @{N = "MemoryMB"; E = {$_.MemoryAssigned / 1MB}}, Uptime, Status ` + | Format-Table -AutoSize + if ($running -ne $null) { + $running + } + else { + Write-Host "VMs are present on this node, but none are currently running." ` + -ForegroundColor White -BackgroundColor Black + } + #--------------------------------------------------------------------- + Write-Host "`n" + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host "NOT RUNNING VMs" -ForegroundColor Red ` + -BackgroundColor Black + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + $notrunning = Get-VM | Where-Object {$_.state -ne 'running'} | Format-Table -AutoSize + if ($notrunning -ne $null) { + $notrunning + } + else { + Write-Host "All VMs on this node report as Running." ` + -ForegroundColor White -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + #--------------------------------------------------------------------- + }#cluster eval + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} +<# +.Synopsis + Name, CPU, DynamicMemoryEnabled, MemoryMinimum(MB), MemoryMaximum(GB), VHDType, VHDSize, VHDMaxSize cluster or standalone hyp +.DESCRIPTION + Gets the VMs configruation info for all VMs. Automatically detects if running on a + standalone hyp or hyp cluster. If standalone is detected it will display VM + configuration information for all VMs on the hyp. If a cluster is detected it will + display VM configuration information for each node in the cluster. +.EXAMPLE + Get-VMInfo + + This command will automatically detect a standalone hyp or hyp cluster and + will retrieve VM configuration information for all detected nodes. +.OUTPUTS + HYP1 + + Name: PSHost-1 + + + Name : PSHost-1 + CPU : 8 + DynamicMemoryEnabled : False + MemoryMinimum(MB) : 1024 + MemoryMaximum(GB) : 24 + VHDType-0 : Differencing + VHDSize(GB)-0 : 10 + MaxSize(GB)-0 : 60 + VHDType-1 : Differencing + VHDSize(GB)-1 : 33 + MaxSize(GB)-1 : 275 + + + + ---------------------------------------------- + HYP2 + No VMs are present on this node. + ---------------------------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info + it will automatically detect standalone or cluster and will run the appropriate diagnostic +.FUNCTIONALITY + Get the following VM information for all detected Hyp nodes: + Name + CPU + DynamicMemoryEnabled + MemoryMinimum(MB) + MemoryMaximum(GB) + IsClustered + ReplicationHealth + OSName + VHDType + VHDSize + VHDMaxSize +#> +function Get-VMInfo { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Verbose "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + #------------------------------------------------------------------------ + Foreach ($node in $nodes) { + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + ##################################### + $object = New-Object -TypeName PSObject + $vms = get-vm -ComputerName $node.name + foreach ($vm in $vms) { + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #_____________________________________________________________ + #_____________________________________________________________ + $opsName = $null + $fqdn = $null + $vmname = "" + $vmname = $vm.name + $query = "Select * From Msvm_ComputerSystem Where ElementName='" + $vmname + "'" + $VmWMI = Get-WmiObject -Namespace root\virtualization\v2 -query $query -computername $node.name -ErrorAction SilentlyContinue + #build KVP object query string + $query = "Associators of {$VmWMI} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent" + #get the VM object + $kvp = $null + $Kvp = Get-WmiObject -Namespace root\virtualization\v2 -query $query -computername $node.name -ErrorAction SilentlyContinue + if ($kvp -ne $null -and $kvp -ne "") { + $obj = $Kvp.GuestIntrinsicExchangeItems | Import-CimXml + $opsName = $obj | Where-Object Name -eq OSName | Select-Object -ExpandProperty Data + $fqdn = $obj | Where-Object Name -eq FullyQualifiedDomainName | Select-Object -ExpandProperty Data + } + if ($opsName -eq $null -or $opsName -eq "") { + $opsName = "Unknown" + } + #_____________________________________________________________ + #_____________________________________________________________ + + $name = $vm | Select-Object -ExpandProperty Name + $object | Add-Member -MemberType NoteProperty -name Name -Value $name -Force + + $cpu = $vm | Select-Object -ExpandProperty ProcessorCount + $object | Add-Member -MemberType NoteProperty -name CPU -Value $cpu -Force + + $dyanamic = $vm | Select-Object -ExpandProperty DynamicMemoryEnabled + $object | Add-Member -MemberType NoteProperty -name DynamicMemoryEnabled -Value $dyanamic -Force + + $memMin = [math]::round($vm.MemoryMinimum / 1MB, 0) + $object | Add-Member -MemberType NoteProperty -name 'MemoryMinimum(MB)' -Value $memMin -Force + + $memMax = [math]::round($vm.MemoryMaximum / 1GB, 0) + $object | Add-Member -MemberType NoteProperty -name 'MemoryMaximum(GB)' -Value $memMax -Force + + $clustered = $vm | Select-Object -ExpandProperty IsClustered + $object | Add-Member -MemberType NoteProperty -name 'IsClustered' -Value $clustered -Force + + $repHealth = $vm | Select-Object -ExpandProperty ReplicationHealth + $object | Add-Member -MemberType NoteProperty -name 'ReplicationHealth' -Value $repHealth -Force + + $osName = $opsName + $object | Add-Member -MemberType NoteProperty -name 'OS Name' -Value $osName -Force + + $object | Add-Member -MemberType NoteProperty -name 'FQDN' -Value $fqdn -Force + + $i = 0 + $vhds = Get-VHD -ComputerName $node.Name -VMId $VM.VMId + foreach ($vhd in $vhds) { + $vhdType = $vhd.vhdtype + $object | Add-Member -MemberType NoteProperty -name "VHDType-$i" -Value $vhdType -Force + #$vhdSize = $vhd.filesize / 1gb –as [int] + [int]$vhdSize = $vhd.filesize / 1gb + $object | Add-Member -MemberType NoteProperty -name "VHDSize(GB)-$i" -Value $vhdSize -Force + #$vhdMaxSize = $vhd.size / 1gb –as [int] + [int]$vhdMaxSize = $vhd.size / 1gb + $object | Add-Member -MemberType NoteProperty -name "MaxSize(GB)-$i" -Value $vhdMaxSize -Force + $i++ + } + $object | Format-List -GroupBy Name + }#foreachVM + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + ##################################### + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #--------------END Get VM Data --------------------- + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + }#nodesForEach + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + }#clusterEval + else { + #standalone server - execute code for standalone server + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + ##################################### + $object = New-Object -TypeName PSObject + $vms = get-vm + foreach ($vm in $vms) { + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #_____________________________________________________________ + #_____________________________________________________________ + $opsName = $null + $vmname = "" + $vmname = $vm.name + $query = "Select * From Msvm_ComputerSystem Where ElementName='" + $vmname + "'" + $VmWMI = Get-WmiObject -Namespace root\virtualization\v2 -query $query -computername localhost -ErrorAction SilentlyContinue + #build KVP object query string + $query = "Associators of {$VmWMI} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent" + #get the VM object + $kvp = $null + $Kvp = Get-WmiObject -Namespace root\virtualization\v2 -query $query -computername localhost -ErrorAction SilentlyContinue + if ($kvp -ne $null -and $kvp -ne "") { + $obj = $Kvp.GuestIntrinsicExchangeItems | Import-CimXml + $opsName = $obj | Where-Object Name -eq OSName | Select-Object -ExpandProperty Data + $fqdn = $obj | Where-Object Name -eq FullyQualifiedDomainName | Select-Object -ExpandProperty Data + } + if ($opsName -eq $null -or $opsName -eq "") { + $opsName = "Unknown" + } + #_____________________________________________________________ + #_____________________________________________________________ + + $name = $vm | Select-Object -ExpandProperty Name + $object | Add-Member -MemberType NoteProperty -name Name -Value $name -Force + + $cpu = $vm | Select-Object -ExpandProperty ProcessorCount + $object | Add-Member -MemberType NoteProperty -name CPU -Value $cpu -Force + + $dyanamic = $vm | Select-Object -ExpandProperty DynamicMemoryEnabled + $object | Add-Member -MemberType NoteProperty -name DynamicMemoryEnabled -Value $dyanamic -Force + + $memMin = [math]::round($vm.MemoryMinimum / 1MB, 0) + $object | Add-Member -MemberType NoteProperty -name 'MemoryMinimum(MB)' -Value $memMin -Force + + $memMax = [math]::round($vm.MemoryMaximum / 1GB, 0) + $object | Add-Member -MemberType NoteProperty -name 'MemoryMaximum(GB)' -Value $memMax -Force + + $clustered = $vm | Select-Object -ExpandProperty IsClustered + $object | Add-Member -MemberType NoteProperty -name 'IsClustered' -Value $clustered -Force + + $repHealth = $vm | Select-Object -ExpandProperty ReplicationHealth + $object | Add-Member -MemberType NoteProperty -name 'ReplicationHealth' -Value $repHealth -Force + + $osName = $opsName + $object | Add-Member -MemberType NoteProperty -name 'OS Name' -Value $osName -Force + + $object | Add-Member -MemberType NoteProperty -name 'FQDN' -Value $fqdn -Force + + $i = 0 + $vhds = Get-VHD -VMId $VM.VMId + foreach ($vhd in $vhds) { + $vhdType = $vhd.vhdtype + $object | Add-Member -MemberType NoteProperty -name "VHDType-$i" -Value $vhdType -Force + #$vhdSize = $vhd.filesize / 1gb –as [int] + [int]$vhdSize = $vhd.filesize / 1gb + $object | Add-Member -MemberType NoteProperty -name "VHDSize(GB)-$i" -Value $vhdSize -Force + #$vhdMaxSize = $vhd.size / 1gb –as [int] + [int]$vhdMaxSize = $vhd.size / 1gb + $object | Add-Member -MemberType NoteProperty -name "MaxSize(GB)-$i" -Value $vhdMaxSize -Force + $i++ + } + $object | Format-List -GroupBy Name + }#foreachVM + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + ##################################### + } + #--------------END Get VM Data --------------------- + }#clusterEval + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} +<# +.Synopsis + Name, Status, ReplicationState, ReplicationHealth, ReplicationMode cluster or standalone hyp +.DESCRIPTION + Gets the VMs replication status info for all VMs. Automatically detects if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM replication status info for all VMs on the hyp. If a cluster is detected it will display VM replication status information for each node in the cluster. +.EXAMPLE + Get-VMReplicationStatus + + This command will automatically detect a standalone hyp or hyp cluster and will retrieve VM replication status information for all detected nodes. +.OUTPUTS + Standalone server detected. Executing standalone diagnostic... + + Name Status ReplicationState ReplicationHealth ReplicationMode + ---- ------ ---------------- ----------------- --------------- + ARK_DC Operating normally Replicating Normal Primary + ARK_DHCP Operating normally Replicating Normal Primary + ARK_MGMT_MDT Operating normally Replicating Normal Primary + ARK_WDS Operating normally Replicating Normal Primary + ARKWSUS Operating normally Replicating Normal Primary +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info + it will automatically detect standalone or cluster and will run the appropriate diagnostic +.FUNCTIONALITY + Get the following VM information for all detected Hyp nodes: + Name + Status + ReplicationState + ReplicationHealth + ReplicationMode +#> +function Get-VMReplicationStatus { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + #------------------------------------------------------------------------ + Foreach ($node in $nodes) { + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM -ComputerName $node.name | Where-Object { $_.ReplicationState -ne "Disabled" } | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + ##################################### + Get-VM | Where-Object { $_.ReplicationState -ne "Disabled" } | Select-Object Name, Status, ReplicationState, ReplicationHealth, ReplicationMode ` + | Format-Table -AutoSize + ##################################### + } + else { + Write-Host "No VMs were detected that have active replication" -ForegroundColor White ` + -BackgroundColor Black + } + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #--------------END Get VM Data --------------------- + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + }#nodesForEach + }#nodesNULLCheck + }#clusterEval + else { + #standalone server - execute code for standalone server + Write-Host "Standalone server detected. Executing standalone diagnostic..." ` + -ForegroundColor Yellow -BackgroundColor Black + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM | Where-Object { $_.ReplicationState -ne "Disabled" } | Measure-Object | Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + ##################################### + Get-VM | Where-Object { $_.ReplicationState -ne "Disabled" } | Select-Object Name, Status, ReplicationState, ReplicationHealth, ReplicationMode ` + | Format-Table -AutoSize + ##################################### + } + else { + Write-Host "No VMs were detected that have active replication" -ForegroundColor White ` + -BackgroundColor Black + } + }#clusterEval + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} +<# +.Synopsis + A VM is comprised of multiple components. Each can reside in a different location. This script will identify the location of all of those components +.DESCRIPTION + A VM is comprised of a few components besides just .vhd/.vhdx. This will retrieve the location paths for the VM's configuration files, Snapshot Files, and Smart Paging files. If on a standalone it will display this information for all VMs on the standalone hyp. If a cluster is detected it will display this information for all VMs found on each node. +.EXAMPLE + Get-VMLocationPathInfo + + This command will display the file paths for all VM components. +.OUTPUTS + Cluster detected. Executing cluster appropriate diagnostic... + ---------------------------------------------- + HypV1 + No VMs are present on this node. + ---------------------------------------------- + Hypv2 + + + VMName : 2008R2Clust + ComputerName : Hypv2 + State : Off + Path : \\sofs-csv\VMs\2008R2Clust + ConfigurationLocation : \\sofs-csv\VMs\2008R2Clust + SnapshotFileLocation : \\sofs-csv\VMs\2008R2Clust + SmartPagingFilePath : \\sofs-csv\VMs\2008R2Clust + ---------------------------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info + it will automatically detect standalone or cluster and will run the appropriate diagnostic +.FUNCTIONALITY + Get the following VM information for all detected Hyp nodes: + VMName + ComputerName + State + ConfigurationLocation + SnapshotFileLocation + SmartPagingFilePath +#> +function Get-VMLocationPathInfo { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Verbose -Message "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #----------------------------------------------------------------------- + Foreach ($node in $nodes) { + try { + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $VMInfo = get-vm -computername $node.name + $VMInfo | Select-Object VMName, ComputerName, State, Path, ` + ConfigurationLocation, SnapshotFileLocation, SmartPagingFilePath ` + | Format-List -GroupBy VMName + #Get-VMHardDiskDrive $VMinfo | Select-Object Name,PoolName,` + #Path,ComputerName,ID,VMName,VMId + } + else { + Write-Host "No VMs are present on this node." ` + -ForegroundColor White -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + } + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + } + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + #----------------------------------------------------------------------- + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + }#clusterEval + else { + #standalone server - execute code for standalone server + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $VMInfo = get-vm -computername $env:COMPUTERNAME + $VMInfo | Select-Object VMName, ComputerName, State, Path, ` + ConfigurationLocation, SnapshotFileLocation, SmartPagingFilePath ` + | Format-List -GroupBy VMName + #Get-VMHardDiskDrive $VMinfo | Select-Object Name,PoolName,` + #Path,ComputerName,ID,VMName,VMId + } + else { + Write-Host "No VMs are present on this node." ` + -ForegroundColor White -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + }#clusterEval + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} +<# +.Synopsis + Displays IntegrationServicesVersion and enabled integration services for all VMs +.DESCRIPTION + Gets the IntegrationServicesVersion and enabled integration services for all VMs. Automatically detects if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM integration services information for all VMs on the hyp. If a cluster is detected it will display VM integration services information for all VMs found on each node. +.EXAMPLE + Get-IntegrationServicesCheck + + This command displays integration services information for all discovered VMs. +.OUTPUTS + ---------------------------------------------- + LinuxTest - no integration services installed + ---------------------------------------------- + LinuxTest3 - no integration services installed + ---------------------------------------------- + LinuxTest4 - no integration services installed + ---------------------------------------------- + PDC2 - version: 6.3.9600.16384 + + Name Enabled + ---- ------- + Time Synchronization True + Heartbeat True + Key-Value Pair Exchange True + Shutdown True + VSS True + Guest Service Interface False + ---------------------------------------------- + TestLinux2 - no integration services installed + ---------------------------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info + it will automatically detect standalone or cluster and will run the appropriate diagnostic +.FUNCTIONALITY + Get the following VM information for all detected Hyp nodes: + IntegrationServicesVersion + Enabled status for all integration services +#> +function Get-IntegrationServicesCheck { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Verbose "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + #-------------------------------------------------------------------------- + Foreach ($node in $nodes) { + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $vms = Get-VM -ComputerName $node.name | Select-Object ` + -ExpandProperty Name + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + foreach ($vm in $vms) { + $version = get-vm -ComputerName $node.name -Name $vm| ` + Select-Object -ExpandProperty integrationservicesversion + if ($version -ne $null) { + Write-Host "$vm - version: $version" -ForegroundColor Magenta + Get-VMIntegrationService -ComputerName $node.name -VMName $vm | ` + Select-Object Name, Enabled | Format-Table -AutoSize + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + else { + Write-Host "$vm - no integration services installed" ` + -ForegroundColor Gray + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + } + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + }#nodesForEach + #----------------------------------------------------------------------- + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + }#clusterEval + else { + #standalone server - execute code for standalone server + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $vms = Get-VM | Select-Object -ExpandProperty Name + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + foreach ($vm in $vms) { + $version = get-vm -Name $vm| Select-Object ` + -ExpandProperty integrationservicesversion + if ($version -ne $null) { + Write-Host "$vm - version: $version" ` + -ForegroundColor Magenta + Get-VMIntegrationService -VMName $vm | Select-Object Name, Enabled | ` + Format-Table -AutoSize + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + else { + Write-Host "$vm - no integration services installed" ` + -ForegroundColor Gray + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + } + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + } + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} +<# +.Synopsis + Evaluates each VM to determine if Hard Drive space is being taken up by the AutomaticStopAction setting +.DESCRIPTION + Checks each VMs RAM and AutomaticStopAction setting - then tallies the amount of total hard drive space being taken up by the associated BIN files. +.EXAMPLE + Get-BINSpaceInfo + + Gets all VMs, their RAM, and their AutomaticStopAction setting +.OUTPUTS + VMName Memory Assigned AutomaticStopAction + ------ --------------- ------------------- + TestVM-1 0 ShutDown + + + ---------------------------------------------- + Total Hard drive space being taken up by BIN files: GB + ---------------------------------------------- + ---------------------------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info + it will automatically detect standalone or cluster and will run the appropriate diagnostic +.FUNCTIONALITY + Get the following VM information for all detected Hyp nodes: + VMName + Memory Assigned + AutomaticStopAction +#> +function Get-BINSpaceInfo { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Verbose "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + #----------------------------------------------------------------------- + $vmMemory = 0 + Foreach ($node in $nodes) { + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + #-----------------Get VM Data Now--------------------- + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $VMInfo = get-vm -computername $node.name + $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' –F ($_.MemoryAssigned / 1GB) } }, ` + AutomaticStopAction | Format-Table -AutoSize + foreach ($vm in $VMInfo) { + if ($vm.AutomaticStopAction -eq "Save") { + $vmMemory += [math]::round($vm.MemoryAssigned / 1GB, 0) + } + } + } + else { + Write-Host "No VMs are present on this node." ` + -ForegroundColor White -BackgroundColor Black + } + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest + #--------------END Get VM Data --------------------- + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + }#nodesForEach + Write-Host "Total Hard drive space being taken up by BIN files: $vmMemory GB" ` + -ForegroundColor Magenta + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #----------------------------------------------------------------------- + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + }#clusterEval + else { + #standalone server - execute code for standalone server + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." + #-----------------Get VM Data Now--------------------- + $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $VMInfo = get-vm + $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' –F ($_.MemoryAssigned/1GB) } },` + AutomaticStopAction | Format-Table -AutoSize + foreach ($vm in $VMInfo) { + if ($vm.AutomaticStopAction -eq "Save") { + $vmMemory += [math]::round($vm.MemoryAssigned / 1GB, 0) + } + } + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host "Total Hard drive space being taken up by BIN files: $vmMemory GB" ` + -ForegroundColor Magenta + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + else { + Write-Host "No VMs are present on this node." ` + -ForegroundColor White -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + }#clusterEval + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} + +#endregion + +#region vhdDiagnosticFunctions + +<# +.Synopsis + For each VM detected every associated VHD/VHDX is identified and several pieces of VHD/VHDX information is displayed +.DESCRIPTION + Identifies all VHDs/VHDXs associated with each VM detected. For each VHD/VHDX it pulls several pieces of information and displays to user. It then sums the current VHD/VHDX disk usage and the POTENTIAL VHD/VHDX disk usage dependent on whether the VHDs/VHDXs are fixed are dynamic. +.EXAMPLE + Get-VMAllVHDs + + Displays information for each VHD for every VM discovered +.OUTPUTS + Standalone server detected. Executing standalone diagnostic... + ---------------------------------------------- + 2008R2Clust2 + + VhdType Size(GB) MaxSize(GB) Path + ------- -------- ----------- ---- + Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx + ---------------------------------------------- + Web1 + + VhdType Size(GB) MaxSize(GB) Path + ------- -------- ----------- ---- + Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx + ---------------------------------------------- + VMs are currently utilizing: 48 GB + VMs could POTENTIALLY Utilize: 180 GB + ---------------------------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info +.FUNCTIONALITY + Get the following VM VHD information for all detected Hyp nodes: + VhdType + Size(GB) + MaxSize(GB) + Path + Total current disk usage + Total POTENTIAL disk usage +#> +function Get-VMAllVHDs { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + #--------------------------------- + [int]$currentStorageUse = $null + [int]$potentialStorageUse = $null + [int]$currentS = $null + [int]$potentialS = $null + #--------------------------------- + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Verbose "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + #------------------------------------------------------------------------ + Foreach ($node in $nodes) { + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + $VMs = Get-VM -ComputerName $node.name + foreach ($VM in $VMs ) { + #---------for output------------- + Write-Host $vm.VMName -ForegroundColor White ` + -BackgroundColor Black + Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` + Format-Table vhdtype, @{label = ’Size(GB)’; ` + expression = {$_.filesize / 1gb –as [int]} + }, ` + @{label = ’MaxSize(GB)’; expression = {$_.size / 1gb –as [int]}}, ` + path -AutoSize + #------END for output------------ + + #------for storage calc---------- + $cs = $null + $cs = Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` + Select-Object -ExpandProperty Filesize + #account for multiple vhds + $cs2 = $null + foreach ($drive in $cs ) { + $cs2 = $cs2 + $drive + } + $ps = $null + $ps = Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` + Select-Object -ExpandProperty Size + #account for multiple vhds + $ps2 = $null + foreach ($drive in $ps ) { + $ps2 = $ps2 + $drive + } + #math time + $cs3 = $null + $ps3 = $null + [int64]$cs3 = [convert]::ToInt64($cs2, 10) + [int64]$ps3 = [convert]::ToInt64($ps2, 10) + $cs3 = $cs3 / 1gb + $ps3 = $ps3 / 1gb + $currentS = $currentS + $cs3 + $potentialS = $potentialS + $ps3 + #------END for storage calc------ + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest + } + catch { + Write-Host "An error was encountered with $node - skipping this node" ` + -ForegroundColor Red + Write-Error $_ + } + }#foreachVM + #------------------------------------------------------------------------ + $currentStorageUse = $currentS + $potentialStorageUse = $potentialS + Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` + -ForegroundColor Magenta + Write-Host "VMs could POTENTIALLY Utilize: " $potentialStorageUse "GB" ` + -ForegroundColor Magenta + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #------------------------------------------------------------------------ + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + }#clusterEval + else { + #------------------------------------------------------------------------ + #standalone server - execute code for standalone server + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." + #-----------------Get VM Data Now--------------------- + Write-Verbose -Message "Getting VM Information..." + $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + #--------------------------------------------------------------------- + $VMs = Get-VM + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + foreach ($VM in $VMs ) { + #---------for output------------- + Write-Host $vm.VMName -ForegroundColor White -BackgroundColor Black + Get-VHD -VMId $VM.VMId | ft vhdtype, @{label = ’Size(GB)’; ` + expression = {$_.filesize / 1gb –as [int]} + }, @{label = ’MaxSize(GB)’; ` + expression = {$_.size / 1gb –as [int]} + }, path -AutoSize + #------END for output------------ + + #------for storage calc---------- + $cs = $null + $cs = Get-VHD -VMId $VM.VMId | Select-Object -ExpandProperty Filesize + #account for multiple vhds + $cs2 = $null + foreach ($drive in $cs ) { + $cs2 = $cs2 + $drive + } + $ps = $null + $ps = Get-VHD -VMId $VM.VMId | Select-Object -ExpandProperty Size + #account for multiple vhds + $ps2 = $null + foreach ($drive in $ps ) { + $ps2 = $ps2 + $drive + } + #math time + $cs3 = $null + $ps3 = $null + [int64]$cs3 = [convert]::ToInt64($cs2, 10) + [int64]$ps3 = [convert]::ToInt64($ps2, 10) + $cs3 = $cs3 / 1gb + $ps3 = $ps3 / 1gb + $currentS = $currentS + $cs3 + $potentialS = $potentialS + $ps3 + #------END for storage calc------ + Write-Host "----------------------------------------------" -ForegroundColor Gray + } + #--------------------------------------------------------------------- + $currentStorageUse = $currentS + $potentialStorageUse = $potentialS + Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` + -ForegroundColor Magenta + Write-Host "VMs could POTENTIALLY Utilize: " $potentialStorageUse "GB" ` + -ForegroundColor Magenta + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #--------------------------------------------------------------------- + } + else { + Write-Host "No VMs are present on this node." ` + -ForegroundColor White -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + }#clusterEval + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} +<# +.Synopsis + For each VM detected every associated VHD/VHDX is checked to determine if the VHD/VHDX is shared or not +.DESCRIPTION + Identifies all VHDs/VHDXs associated with each VM detected. For each VHD/VHDX it pulls several pieces of information to display to user. If SupportPersistentReservations is true, the VHD/VHDX is shared. +.EXAMPLE + Get-SharedVHDs + + Displays SupportPersistentReservations information for each VHD for every VM discovered. If SupportPersistentReservations is true, the VHD is shared +.OUTPUTS + Standalone server detected. Executing standalone diagnostic... + ---------------------------------------------- + 2008R2Clust2 + + VhdType Size(GB) MaxSize(GB) Path + ------- -------- ----------- ---- + Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx + ---------------------------------------------- + Web1 + + VhdType Size(GB) MaxSize(GB) Path + ------- -------- ----------- ---- + Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx + ---------------------------------------------- + VMs are currently utilizing: 48 GB + VMs could POTENTIALLY Utilize: 180 GB + ---------------------------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info +.FUNCTIONALITY + Get the following VM VHD information for all detected Hyp nodes: + VMName + SupportPersistentReservations + Path +#> +function Get-SharedVHDs { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + if ($nodes -ne $null) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` + -ForegroundColor Yellow -BackgroundColor Black + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + #--------------------------------------------------------------------- + Foreach ($node in $nodes) { + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + $quickCheck = Get-VM -ComputerName $node.name | measure | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + get-vm -ComputerName $node.name | Get-VMHardDiskDrive | select VMName, ` + supportpersistentreservations, path | ft -AutoSize + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + #--------------------------------------------------------------------- + + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + } + else { + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + } + } + catch { + Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` + -ForegroundColor Red + } + } + } + else { + #standalone server - execute code for standalone server + Write-Host "Standalone server detected. Executing standalone diagnostic..." ` + -ForegroundColor Yellow -BackgroundColor Black + $quickCheck = Get-VM | measure | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + #--------------------------------------------------------------------- + get-vm | Get-VMHardDiskDrive | select VMName, ` + supportpersistentreservations, path | ft -AutoSize + #--------------------------------------------------------------------- + + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + } + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} + +#endregion + +#region guiMenu + +<# +.Synopsis + Collection of several Hyper-V diagnostics that can be run via a simple choice menu +.DESCRIPTION + Diag-V is a collection of various Hyper-V diagnostics. It presents the user + a simple choice menu that allows the user to select and execute the desired + diagnostic. Each diagnostic is a fully independent function which can be + copied and run independent of Diag-V if desired. +.EXAMPLE + Diag-V + + Copy code into an administrative PS or ISE window and run. +.OUTPUTS + Output will vary depending on the selected diagnostic. + + ############################################## + ____ _ __ __ + | _ \(_) __ _ __ _ \ \ / / + | | | | |/ _ |/ _ |____\ \ / / + | |_| | | (_| | (_| |_____\ V / + |____/|_|\__,_|\__, | \_/ + |___/ + ############################################## + A Hyper-V diagnostic utility + ############################################## + MAIN MENU + ############################################## + [1] VMs + [2] VHDs + [3] Overallocation + [4] CSVs + [5] Hyper-V Event Logs + Please select a menu number: +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info +.FUNCTIONALITY + Get-VMStatus + ------------------------------ + Get-VMInfo + ------------------------------ + Get-VMReplicationStatus + ------------------------------ + Get-VMLocationPathInfo + ------------------------------ + Get-VMDetails + ------------------------------ + Get-IntegrationServicesCheck + ------------------------------ + Get-BINSpaceInfo + ------------------------------ + Get-VMAllVHDs + ------------------------------ + Get-SharedVHDs + ------------------------------ + Test-HyperVAllocation + ------------------------------ + Get-CSVtoPhysicalDiskMapping + ------------------------------ + Get-FileSizes +#> +function Show-DiagVMenu { + #all this serves to do is to launch the parent menu choice option + showTheTopLevel +} +#################################################################################### +#------------------------------Menu Selections-------------------------------------- +#################################################################################### +<# +.Synopsis + showTheTopLevel is a menu level function that shows the parent (or top) menu choices +.DESCRIPTION + showTheTopLevel is a menu level function that shows the parent (or top) menu choices +#> +function showTheTopLevel { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " MAIN MENU" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + + Write-Host "[1] VMs" + Write-Host "[2] VHDs" + Write-Host "[3] Overallocation" + Write-Host "[4] CSVs" + Write-Host "[5] Hyper-V Event Logs" + + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + showVMDiags + } + elseif ($topLevel -eq 2) { + showVHDDiags + } + elseif ($topLevel -eq 3) { + showAllocationDiags + } + elseif ($topLevel -eq 4) { + showCSVDiags + } + elseif ($topLevel -eq 5) { + showHyperVLogs + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# +.Synopsis + showTheTopLevel is a menu level function that shows the VM diagnostic menu choices +.DESCRIPTION + showTheTopLevel is a menu level function that shows the VM diagnostic menu choices +#> +function showVMDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " VM Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-VMStatus" + Write-Host "[2] Get-VMInfo" + Write-Host "[3] Get-VMReplicationStatus" + Write-Host "[4] Get-VMLocationPathInfo" + Write-Host "[5] Get-IntegrationServicesCheck" + Write-Host "[6] Get-BINSpaceInfo" + Write-Host "[7] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-VMStatus + } + elseif ($topLevel -eq 2) { + Get-VMInfo + } + elseif ($topLevel -eq 3) { + Get-VMReplicationStatus + } + elseif ($topLevel -eq 4) { + Get-VMLocationPathInfo + } + elseif ($topLevel -eq 5) { + Get-IntegrationServicesCheck + } + elseif ($topLevel -eq 6) { + Get-BINSpaceInfo + } + elseif ($topLevel -eq 7) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# +.Synopsis + showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices +.DESCRIPTION + showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices +#> +function showVHDDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " VHD Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-VMAllVHDs" + Write-Host "[2] Get-SharedVHDs" + Write-Host "[3] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-VMAllVHDs + } + elseif ($topLevel -eq 2) { + Get-SharedVHDs + } + elseif ($topLevel -eq 3) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# +.Synopsis + showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices +.DESCRIPTION + showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices +#> +function showAllocationDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " OverAllocation Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Test-HyperVAllocation" + Write-Host "[2] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Test-HyperVAllocation + } + elseif ($topLevel -eq 2) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# +.Synopsis + showCSVDiags is a menu level function that shows the CSV diagnostic menu choices +.DESCRIPTION + showCSVDiags is a menu level function that shows the CSV diagnostic menu choices +#> +function showCSVDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " CSV Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-CSVtoPhysicalDiskMapping" + Write-Host "[2] Get-FileSizes" + Write-Host "[3] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-CSVtoPhysicalDiskMapping + } + elseif ($topLevel -eq 2) { + Get-FileSizes + } + elseif ($topLevel -eq 3) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} + +<# +.Synopsis + showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices +.DESCRIPTION + showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices +#> +function showHyperVLogs { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " Hyper-V Event Log Search" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Search last 24 hours" + Write-Host "[2] Specify date range" + Write-Host "[3] Main Menu" + + $MenuChoice = $null + $MenuChoice = Read-Host "Please select a menu number" + + if ($MenuChoice -eq 3) { + showTheTopLevel + } + else { + Get-ClusterCheck + } +} + +#################################################################################### +#-----------------------------END Menu Selections----------------------------------- +#################################################################################### + +#endregion \ No newline at end of file diff --git a/Overallocation/Test-HyperVAllocation.ps1 b/Overallocation/Test-HyperVAllocation.ps1 deleted file mode 100644 index 44d31ec..0000000 --- a/Overallocation/Test-HyperVAllocation.ps1 +++ /dev/null @@ -1,522 +0,0 @@ -<# -.Synopsis - Determines the current resource allocation health of Hyper-V Server or Hyper-V Cluster -.DESCRIPTION - For single Hyper-V instances this function will pull available - CPU and Memory physical resources. It will then tally all VM CPU and memory - allocations and contrast that info with available physical resources - - A cpu ratio higher than 4:1 (vCPU:Logical Processors) will be flagged as bad - A static memory higher than 1:1 will be flagged as bad - There is no best practice published around dynamic maximum memory so the function - will only advise a warning if max memory is higher than available physical memory. - - The same functionality is supported for clustered Hyper-V instances. - The function will poll each node in the cluster and provide info on each node. - The cluster function will also calculate the simulation loss of one node to determine - if VMs could survive and start with one node down. - - Available storage space will also be calculated. For clusters CSV locations will be - checked. For standalone Hyps any drive larger than 10GB and not C: will be checked. - In keeping with best practices anything with less than 20% free space will fail the - health check. -.EXAMPLE - Test-HyperVAllocation - - If executed on a standalone Hyper-V instance it will retrieve CPU/RAM physical resources - If exectured on a Hyper-V cluster it will retrieve CPU/RAM physical resrouces for - all nodes in the cluster and comapares those available resources to resources assigned - to VMs on each Hyper-V instance. -.OUTPUTS - ----------------------------- - SystemName: 80167-hyp2 - ----------------------------- - Cores: 24 - Logical Processors: 48 - Total Memory: 256 GB - Free Memory: 248 GB - Number of VMs: 1 - Number of VM Procs: 2 - ----------------------------- - Memory resources are still available: 97 % free - ----------------------------- - Virtual Processors are not overprovisioned 1 : 1 - ----------------------------- - Total Startup memory required for Dynamic VMs: 0 GB - Total Static memory required for Static VMs: 29 GB - ----------------------------- - Total minimum RAM (Startup+Static) required: 29 GB - Minimum RAM: 29 GB does not exceed available RAM: 256 GB - ----------------------------- - VMs would survive a one node failure - Total VM RAM minumum: 56 GB - Total Cluster RAM available with one node down: 256 GB - ----------------------------- - Storage Allocation Information - ----------------------------- - C:\ClusterStorage\Volume2 has the recommended 20% free space. - Free Space: 100 GB - Percent Free: 99.87756 - ----------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - You can change the CPU ratio cutoff from 4:1 to say 6:1 or 8:1 by editing the - Highlighted section below to suit your requirements -.FUNCTIONALITY - Get the following information for each Hyper-V instance found - System Name - Logical Processors - Total Memory - Free Memory - Number of VMs - Number of VM Procs - CPU provisioning status - Memory provisioning status - Free space status -#> -function Test-HyperVAllocation{ - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - foreach($node in $nodes){ - if(Test-Connection -ComputerName $node){ - - } - else{ - Write-Host "Not all nodes could be reached - please address $node" -ForegroundColor Red - return - } - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - - if($nodes -ne $null){ - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." -ForegroundColor Yellow -BackgroundColor Black - $totalClusterRAM = $null - $totalVMClusterRAM = $null - $nodeCount = 0 - #######################CLUSTER DIAG######################## - #we are definitely dealing with a cluster - execute code for cluster - #--------------------------------------------------------------------- - Foreach($node in $nodes){ - $w32ProcInfo = $null - $w32OSInfo = $null - $name = $null - $numCores = $null - $numLogicProcs = $null - $totalNumCores = $null - $totalNumLogicProcs =$null - [double]$totalMemory = $null - [double]$freeMemory = $null - $nodeCount += 1 - #--------------------------------------------------------------------- - #get WMI data loaded up - #-------------------------------------------------------------------- - try{ - $w32ProcInfo = Get-WmiObject -Namespace "root\cimv2" -Class win32_processor -Impersonation 3 -ComputerName $node - $w32OSInfo = Get-WmiObject -Namespace "root\cimv2" -Class Win32_OperatingSystem -Impersonation 3 -ComputerName $node - } - catch{ - Write-Host "An error was encountered getting WMI info from $node" -ForegroundColor Red - Write-Error $_ - Return - } - #-------------------------------------------------------------------- - #load specific WMI data into variables - #-------------------------------------------------------------------- - $name = $node - $numCores = $w32ProcInfo.numberOfCores - foreach($core in $numCores){ - $totalNumCores += $core - } - $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors - foreach($proc in $numLogicProcs){ - $totalNumLogicProcs += $proc - } - $totalMemory = [math]::Round($w32OSInfo.TotalVisibleMemorySize /1MB, 0) - $freeMemory = [math]::Round($w32OSInfo.FreePhysicalMemory /1MB, 0) - $totalClusterRAM += $totalMemory - #-------------------------------------------------------------------- - #-------------------------------------------------------------------- - #load VM data and count number of VMs and VMs processors - #-------------------------------------------------------------------- - $vms = $null - $vmCount = $null - $vmProcCount = $null - $totalVMProcCount = $null - try{ - $vms = Get-VM -ComputerName $node - $vmCount = $vms | measure | Select-Object -ExpandProperty count - $vmProcCount = $vms | Get-VMProcessor | Select-Object -ExpandProperty count - } - catch{ - Write-Host "An error was encountered getting VM info from $node" -ForegroundColor Red - Write-Error $_ - Return - } - - foreach($proc in $vmProcCount){ - $totalVMProcCount += $proc - } - #-------------------------------------------------------------------- - #null all counts to permit multiple script runs - #-------------------------------------------------------------------- - $memorystartup = 0 - $MemoryMaximum = 0 - $totalstartupmem = 0 - $totalmaxmem = 0 - $static = 0 - $staticmemory = 0 - #-------------------------------------------------------------------- - #calculate memory usage dynamic/static for each VM to generate totals - #-------------------------------------------------------------------- - foreach ($vm in $vms) { - if ((Get-VMMemory -ComputerName $node -vmname $vm.Name).DynamicMemoryEnabled -eq "True") { - $memoryStartup = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup /1GB, 0) - $memoryMaximum = [math]::Round(($VM | select-object MemoryMaximum).memorymaximum /1GB, 0) - $totalstartupmem += $memoryStartup - $totalmaxmem += $memoryMaximum - } - else { - $static = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) - $staticmemory += $static - } - } - $totalramrequired=$totalstartupmem + $staticmemory - $totalVMClusterRAM += $totalramrequired - #account for no static and no dynamic situations - if($totalstartupmem -eq $null){ - $totalstartupmem = 0 - } - if($staticmemory -eq $null){ - $staticmemory = 0 - } - #-------------------------------------------------------------------- - #output basic information about server - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "SystemName:" $name - Write-Host "-----------------------------" - Write-Host "Cores:" $totalNumCores - Write-Host "Logical Processors:" $totalNumLogicProcs - Write-Host "Total Memory:" $totalMemory GB - Write-Host "Free Memory:" $freeMemory GB - Write-Host "Number of VMs:" $vmCount - Write-Host "Number of VM Procs:" $totalVMProcCount - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #current memory usage status: - #-------------------------------------------------------------------- - #total memory vs free memory - less than 10% free is considered bad - $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100 - if($memPercent -lt 10){ - Write-Host "This system is low on memory resources: $memPercent % free" -ForegroundColor Red - } - else{ - Write-Host "Memory resources are still available: $memPercent % free" -ForegroundColor Green - } - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #cpu ratio output - #-------------------------------------------------------------------- - #$vmProcCount = 49 - if($totalVMProcCount -gt $totalNumLogicProcs){ - $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount) - $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs) - #--------DEFAULT IS 4:1 which is 1/4 = .25------------------------ - if($cpuRatio -lt .25){ - #adjust above this line to achieve desired ratio------------------ - $procRatio +=1 - Write-Host "Overprovisioned on Virtual processors." $procRatio ": 1" -ForegroundColor Red - } - else{ - Write-Host "Virtual Processors not overprovisioned" $procRatio ": 1" -ForegroundColor Green - } - } - else{ - Write-Host "Virtual Processors are not overprovisioned 1 : 1" -ForegroundColor Green - } - #-------------------------------------------------------------------- - #memory ratio information - #-------------------------------------------------------------------- - write-host "-----------------------------" - write-host "Total Startup memory required for Dynamic VMs: $totalstartupmem GB " - write-host "Total Static memory required for Static VMs: $staticmemory GB " - write-host "-----------------------------" - write-host "Total minimum RAM (Startup+Static) required: $totalramrequired GB " - if($totalramrequired -lt $totalMemory){ - Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Minimum RAM: $totalramrequired GB exceeds available RAM: $totalMemory GB" -ForegroundColor Red - } - write-host "-----------------------------" - if($totalmaxmem -ne 0){ - write-host "Total *Potential* Maximum memory for Dynamic VMs: $totalmaxmem GB" - if($totalmaxmem -lt $totalMemory){ - Write-Host "Maximum potential RAM: $totalmaxmem GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Maximum potential RAM: $totalmaxmem GB exceeds available RAM: $totalMemory GB" -ForegroundColor Yellow - } - } - #-------------------------------------------------------------------- - } - #calculating a node loss and its impact - $x = $totalClusterRAM / $nodeCount - $clusterNodeDownUseable = $totalClusterRAM - $x - if($totalVMClusterRAM -gt $clusterNodeDownUseable){ - Write-Host "VMs would NOT survive a one node failure" -ForegroundColor Red - Write-Host "Total VM RAM minumum: $totalVMClusterRAM GB - Total Cluster RAM available with one node down: $clusterNodeDownUseable GB" -ForegroundColor Cyan - } - else{ - Write-Host "VMs would survive a one node failure" -ForegroundColor Green - Write-Host "Total VM RAM minumum: $totalVMClusterRAM GB - Total Cluster RAM available with one node down: $clusterNodeDownUseable GB" -ForegroundColor Cyan - } - #-------------------------------------------------------------------- - #CSV Storage Space checks - we will check CSV locations only for clustered Hyps - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "Storage Allocation Information" - Write-Host "-----------------------------" - try{ - $clusterName = "." - $clusterSharedVolume = Get-ClusterSharedVolume -Cluster $clusterName ` - -ErrorAction SilentlyContinue - if ($clusterSharedVolume -eq $null){ - Write-Host "No CSVs discovered - no storage information pulled" ` - -ForegroundColor Yellow - } - else{ - foreach ($volume in $clusterSharedVolume){ - $volumeowner = $volume.OwnerNode.Name - $csvVolume = $volume.SharedVolumeInfo.Partition.Name - $cimSession = New-CimSession -ComputerName $volumeowner - $volumeInfo = Get-Disk -CimSession $cimSession | Get-Partition | ` - Select DiskNumber, @{Name="Volume"; ` - Expression={Get-Volume -Partition $_ | ` - Select -ExpandProperty ObjectId} - } - $csvdisknumber = ($volumeinfo | where ` - { $_.Volume -eq $csvVolume}).Disknumber - $diskName = $volume.SharedVolumeInfo.FriendlyVolumeName - $percentFree = $volume.SharedVolumeInfo.Partition.PercentFree - $spaceFree = [int]($volume.SharedVolumeInfo.Partition.Freespace/1GB) - if($percentFree -lt 20){ - Write-Host $diskName "is below the recommended 20% free space." -ForegroundColor Red - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Red - Write-Host "Percent Free: $percentFree" -ForegroundColor Red - Write-Host "-----------------------------" - } - else{ - Write-Host $diskName "has the recommended 20% free space." -ForegroundColor Green - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Gray - Write-Host "Percent Free: $percentFree" -ForegroundColor Gray - Write-Host "-----------------------------" - } - } - } - - } - catch{ - Write-Host "ERROR - An issue was encountered getting CSVs spacing information:" ` - -ForegroundColor Red - } - #######################END CLUSTER DIAG######################## - } - else{ - #standalone server - execute code for standalone server - #######################STANDALONE DIAG######################## - Write-Host "Standalone server detected. Executing standalone diagnostic..." -ForegroundColor Yellow -BackgroundColor Black - #--------------------------------------------------------------------- - #get WMI data loaded up - #-------------------------------------------------------------------- - try{ - $w32ProcInfo = Get-WmiObject -class win32_processor - $w32OSInfo = Get-WMIObject -class Win32_OperatingSystem - } - catch{ - Write-Host "An error was encountered getting WMI info from $node" -ForegroundColor Red - Write-Error $_ - Return - } - #-------------------------------------------------------------------- - #load specific WMI data into variables - #-------------------------------------------------------------------- - $name = $w32ProcInfo.systemname - $numCores = $w32ProcInfo.numberOfCores - foreach($core in $numCores){ - $totalNumCores += $core - } - $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors - foreach($proc in $numLogicProcs){ - $totalNumLogicProcs += $proc - } - $totalMemory = [math]::round($w32OSInfo.TotalVisibleMemorySize /1MB, 0) - $freeMemory = [math]::round($w32OSInfo.FreePhysicalMemory /1MB, 0) - #-------------------------------------------------------------------- - #load VM data and count number of VMs and VMs processors - #-------------------------------------------------------------------- - try{ - $vms = Get-VM - $vmCount = $vms | measure | Select-Object -ExpandProperty count - $vmProcCount = $vms | Get-VMProcessor | Select-Object -ExpandProperty count - } - catch{ - Write-Host "An error was encountered getting VM info" -ForegroundColor Red - Write-Error $_ - Return - } - - foreach($proc in $vmProcCount){ - $totalVMProcCount += $proc - } - #-------------------------------------------------------------------- - #null all counts to permit multiple script runs - #-------------------------------------------------------------------- - $memorystartup = 0 - $MemoryMaximum = 0 - $totalstartupmem = 0 - $totalmaxmem = 0 - $static = 0 - $staticmemory = 0 - #-------------------------------------------------------------------- - #calculate memory usage dynamic/static for each VM to generate totals - #-------------------------------------------------------------------- - foreach ($vm in $vms) { - if ((Get-VMMemory -vmname $vm.Name).DynamicMemoryEnabled -eq "True") { - $memorystartup = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) - $memoryMaximum = [math]::Round(($VM | select-object MemoryMaximum).memorymaximum / 1GB, 0) - - $totalstartupmem += $memoryStartup - $totalmaxmem += $memoryMaximum - } - else { - $static = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) - $staticmemory += $static - } - } - $totalramrequired=$totalstartupmem + $staticmemory - #account for no static and no dynamic situations - if($totalstartupmem -eq $null){ - $totalstartupmem = 0 - } - if($staticmemory -eq $null){ - $staticmemory = 0 - } - #-------------------------------------------------------------------- - #output basic information about server - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "SystemName:" $name - Write-Host "-----------------------------" - Write-Host "Cores:" $totalNumCores - Write-Host "Logical Processors:" $totalNumLogicProcs - Write-Host "Total Memory:" $totalMemory GB - Write-Host "Free Memory:" $freeMemory GB - Write-Host "Number of VMs:" $vmCount - Write-Host "Number of VM Procs:" $totalVMProcCount - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #current memory usage status: - #-------------------------------------------------------------------- - #total memory vs free memory - less than 10% free is considered bad - $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100 - if($memPercent -lt 10){ - Write-Host "This system is low on memory resources: $memPercent % free" -ForegroundColor Red - } - else{ - Write-Host "Memory resources are still available: $memPercent % free" -ForegroundColor Green - } - Write-Host "-----------------------------" - #-------------------------------------------------------------------- - #cpu ratio output - #-------------------------------------------------------------------- - #$vmProcCount = 49 - if($totalVMProcCount -gt $totalNumLogicProcs){ - $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount) - $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs) - #$procRatio2 = [math]::round($procRatio / $cpuRatio) - #------------HERE YOU CAN CHANGE CPU RATIO TO DESIRED RATIO------- - #--------DEFAULT IS 4:1 which is 1/4 = .25------------------------ - if($cpuRatio -lt .25){ - #adjust above this line to achieve desired ratio------------------ - $procRatio +=1 - Write-Host "Overprovisioned on Virtual processors." $procRatio ": 1" -ForegroundColor Red - } - else{ - Write-Host "Virtual Processors not overprovisioned" $procRatio ": 1" -ForegroundColor Green - } - } - else{ - Write-Host "Virtual Processors are not overprovisioned 1 : 1" -ForegroundColor Green - } - #-------------------------------------------------------------------- - #memory ratio information - #-------------------------------------------------------------------- - write-host "-----------------------------" - write-host "Total Startup memory required for Dynamic VMs: $totalstartupmem GB " - write-host "Total Static memory required for Static VMs: $staticmemory GB " - write-host "-----------------------------" - write-host "Total minimum RAM (Startup+Static) required: $totalramrequired GB " - if($totalramrequired -lt $totalMemory){ - Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Minimum RAM: $totalramrequired GB exceeds available RAM: $totalMemory GB" -ForegroundColor Red - } - write-host "-----------------------------" - if($totalmaxmem -ne 0){ - write-host "Total *Potential* Maximum memory for Dynamic VMs: $totalmaxmem GB" - if($totalmaxmem -lt $totalMemory){ - Write-Host "Maximum potential RAM: $totalmaxmem GB does not exceed available RAM: $totalMemory GB" -ForegroundColor Green - } - else{ - Write-Host "Maximum potential RAM: $totalmaxmem GB exceeds available RAM: $totalMemory GB" -ForegroundColor Yellow - } - } - #-------------------------------------------------------------------- - #Storage Space checks - we will check all drives greater than 10GB that are no C: - #-------------------------------------------------------------------- - Write-Host "-----------------------------" - Write-Host "Storage Allocation Information" - Write-Host "-----------------------------" - $drives = Get-WmiObject win32_logicaldisk -ErrorAction SilentlyContinue | Where-Object {$_.DeviceID -ne "C:"} - if($drives -ne $null){ - foreach($drive in $drives){ - $totalSize = [int]($drive.Size/1GB) - if($totalSize -gt 10){ - $driveLetter = $drive.DeviceID - $spaceFree = [int]($drive.Freespace/1GB) - $percentFree = [math]::round(($spaceFree / $totalSize) * 100) - if($percentFree -lt 20){ - Write-Host $driveLetter "is below the recommended 20% free space." -ForegroundColor Red - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Red - Write-Host "Percent Free: $percentFree" -ForegroundColor Red - Write-Host "-----------------------------" - } - else{ - Write-Host $driveLetter "has the recommended 20% free space." -ForegroundColor Green - Write-Host "Free Space: $spaceFree GB" -ForegroundColor Gray - Write-Host "Percent Free: $percentFree" -ForegroundColor Gray - Write-Host "-----------------------------" - } - } - } - } - else{ - Write-Host "No additional storage other than OS drive deteceted" ` - -ForegroundColor Yellow - } - #######################STANDALONE DIAG######################## - #-------------------------------------------------------------------- - } -} \ No newline at end of file diff --git a/README.md b/README.md index 5420ac8..30a2694 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +#THIS BRANCH IS NOT PRODUCTION READY AT THIS TIME + # Diag-V Hyper-V Diagnostic Utility diff --git a/VMs/Get-IntegrationServicesCheck.ps1 b/VMs/Get-IntegrationServicesCheck.ps1 deleted file mode 100644 index 745a38f..0000000 --- a/VMs/Get-IntegrationServicesCheck.ps1 +++ /dev/null @@ -1,166 +0,0 @@ -<# -.Synopsis - Displays IntegrationServicesVersion and enabled integration services for all VMs -.DESCRIPTION - Gets the IntegrationServicesVersion and enabled integration services for all VMs. - Automatically detects if running on a standalone hyp or hyp cluster. - If standalone is detected it will display VM integration services information - for all VMs on the hyp. If a cluster is detected it will display VM integration - services information for all VMs found on each node. -.EXAMPLE - Get-IntegrationServicesCheck - - This command displays integration services information for all discovered VMs. -.OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - LinuxTest - no integration services installed - ---------------------------------------------- - LinuxTest3 - no integration services installed - ---------------------------------------------- - LinuxTest4 - no integration services installed - ---------------------------------------------- - PDC2 - version: 6.3.9600.16384 - - Name Enabled - ---- ------- - Time Synchronization True - Heartbeat True - Key-Value Pair Exchange True - Shutdown True - VSS True - Guest Service Interface False - ---------------------------------------------- - TestLinux2 - no integration services installed - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: - IntegrationServicesVersion - Enabled status for all integration services -#> -#it will automatically detect standalone or cluster and will run the appropriate diagnostic -function Get-IntegrationServicesCheck{ - Write-Host "This will not find any VMs if you are not running PowerShell as admin!" ` - -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #-------------------------------------------------------------------------- - Foreach($node in $nodes){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $vms = Get-VM -ComputerName $node.name | Select-Object ` - -ExpandProperty Name - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - foreach ($vm in $vms){ - $version = get-vm -ComputerName $node.name -Name $vm| ` - Select-Object -ExpandProperty integrationservicesversion - if($version -ne $null){ - Write-Host "$vm - version: $version" -ForegroundColor Magenta - Get-VMIntegrationService -ComputerName $node.name -VMName $vm | ` - select Name,Enabled | ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - else{ - Write-Host "$vm - no integration services installed" ` - -ForegroundColor Gray - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - } - - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - #----------------------------------------------------------------------- - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #--------------------------------------------------------------------- - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $vms = Get-VM | Select-Object -ExpandProperty Name - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - foreach ($vm in $vms){ - $version = get-vm -Name $vm| Select-Object ` - -ExpandProperty integrationservicesversion - if($version -ne $null){ - Write-Host "$vm - version: $version" ` - -ForegroundColor Magenta - Get-VMIntegrationService -VMName $vm | select Name,Enabled | ` - ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - else{ - Write-Host "$vm - no integration services installed" ` - -ForegroundColor Gray - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - } - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - #--------------------------------------------------------------------- - } -} \ No newline at end of file diff --git a/VMs/Get-VMLocationPathInfo.ps1 b/VMs/Get-VMLocationPathInfo.ps1 deleted file mode 100644 index 16923be..0000000 --- a/VMs/Get-VMLocationPathInfo.ps1 +++ /dev/null @@ -1,137 +0,0 @@ -<# -.Synopsis - A VM is comprised of multiple components. Each can reside in a different - location. This script will identify the location of all of those components -.DESCRIPTION - A VM is comprised of a few components besides just .vhd/.vhdx. This will - retrieve the location paths for the VM's configuration files, Snapshot Files, - and Smart Paging files. If on a standalone it will display this information - for all VMs on the standalone hyp. If a cluster is detected it will display - this information for all VMs found on each node. -.EXAMPLE - Get-VMLocationPathInfo - - This command will display the file paths for all VM components. -.OUTPUTS - Cluster detected. Executing cluster appropriate diagnostic... - ---------------------------------------------- - HypV1 - No VMs are present on this node. - ---------------------------------------------- - Hypv2 - - - VMName : 2008R2Clust - ComputerName : Hypv2 - State : Off - Path : \\sofs-csv\VMs\2008R2Clust - ConfigurationLocation : \\sofs-csv\VMs\2008R2Clust - SnapshotFileLocation : \\sofs-csv\VMs\2008R2Clust - SmartPagingFilePath : \\sofs-csv\VMs\2008R2Clust - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: - VMName - ComputerName - State - ConfigurationLocation - SnapshotFileLocation - SmartPagingFilePath -#> -#it will automatically detect standalone or cluster and will run the appropriate diagnostic -function Get-VMLocationPathInfo{ - Write-Host "This will not find any VMs if you are not running PowerShell as" ` - "admin!" -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #----------------------------------------------------------------------- - Foreach($node in $nodes){ - try{ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $VMInfo = get-vm -computername $node.name - $VMInfo | Select-Object VMName,ComputerName,State,Path,` - ConfigurationLocation,SnapshotFileLocation,SmartPagingFilePath - #Get-VMHardDiskDrive $VMinfo | Select-Object Name,PoolName,` - #Path,ComputerName,ID,VMName,VMId - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - #----------------------------------------------------------------------- - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #--------------------------------------------------------------------- - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $VMInfo = get-vm -computername $env:COMPUTERNAME - $VMInfo | Select-Object VMName,ComputerName,State,Path,` - ConfigurationLocation,SnapshotFileLocation,SmartPagingFilePath - #Get-VMHardDiskDrive $VMinfo | Select-Object Name,PoolName,` - #Path,ComputerName,ID,VMName,VMId - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - #--------------------------------------------------------------------- - } -} \ No newline at end of file diff --git a/VMs/Get-VMStatus.ps1 b/VMs/Get-VMStatus.ps1 deleted file mode 100644 index cb0dd23..0000000 --- a/VMs/Get-VMStatus.ps1 +++ /dev/null @@ -1,240 +0,0 @@ -<# -.Synopsis - Name, State, CPUUsage, Memory usage, Uptime, and Status of all VMs on a - cluster or standalone hyp -.DESCRIPTION - Gets the status of all discovered VMs. Automatically detects if running on a - standalone hyp or hyp cluster. If standalone is detected it will display VM - status information for all VMs on the hyp. If a cluster is detected it will - display VM status information for each node in the cluster. -.EXAMPLE - Get-VMStatus - - This command will automatically detect a standalone hyp or hyp cluster and - will retrieve VM status information for all detected nodes. -.OUTPUTS - Cluster detected. Executing cluster appropriate diagnostic... - ---------------------------------------------- - RUNNING VMs - ---------------------------------------------- - HypV1 - No VMs are present on this node. - ---------------------------------------------- - Hypv2 - There are no running VMs - probably not a good thing. Fix it. - ---------------------------------------------- - - - ---------------------------------------------- - NOT RUNNING VMs - ---------------------------------------------- - HypV1 - No VMs are present on this node. - ---------------------------------------------- - Hypv2 - - Name State CPUUsage(%) MemoryAssigned(M) Uptime Status - ---- ----- ----------- ----------------- ------ ------ - 2008R2Clust Off 0 0 00:00:00 Operating normally - 2008R2Clust2 Off 0 0 00:00:00 Operating normally - 2012R2Clust Off 0 0 00:00:00 Operating normally - 2012R2Clust2 Off 0 0 00:00:00 Operating normally - Web1 Off 0 0 00:00:00 Operating normally - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: - Name - State - CPUUsage - Memory - Uptime - Status -#> -#it will automatically detect standalone or cluster and will run the appropriate diagnostic -function Get-VMStatus{ - Write-Host "This will not find any VMs if you are not running PowerShell as admin!" ` - -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #------------------------------------------------------------------------ - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "RUNNING VMs" -ForegroundColor Green ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Foreach($node in $nodes){ - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - #-----------------Get VM Data Now--------------------- - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $running = Get-VM -ComputerName $node.name | ` - where {$_.state -eq 'running'} | sort Uptime | ` - select Name,State,CPUUsage,` - @{N="MemoryMB";E={$_.MemoryAssigned/1MB}},Uptime,Status,` - IsClustered| ft -AutoSize - if($running -ne $null){ - $running - } - else{ - Write-Host "There are no running VMs - probably not a good thing."` - " Fix it." -ForegroundColor White -BackgroundColor Black - } - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------END Get VM Data --------------------- - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - Write-Host "`n" - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "NOT RUNNING VMs" -ForegroundColor Red ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Foreach($node in $nodes){ - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - Write-Host $node.name -ForegroundColor White ` - -BackgroundColor Black - #-----------------Get VM Data Now--------------------- - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $notrunning = Get-VM -ComputerName $node.name | ` - where {$_.state -ne 'running'} | ` - select Name,State,CPUUsage,` - @{N="MemoryMB";E={$_.MemoryAssigned/1MB}},Status,` - IsClustered| ft -AutoSize | ft -AutoSize - if($notrunning -ne $null){ - $notrunning - } - else{ - Write-Host "All VMs are currently running - HOORAY!" ` - -ForegroundColor White -BackgroundColor Black - } - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------END Get VM Data --------------------- - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - #------------------------------------------------------------------------ - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #-----------------Get VM Data Now--------------------- - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "RUNNING VMs" -ForegroundColor Green ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - $running = Get-VM | where {$_.state -eq 'running'} | sort Uptime | ` - select Name,State,CPUUsage,` - @{N="MemoryMB";E={$_.MemoryAssigned/1MB}},Uptime,Status ` - | ft -AutoSize - if($running -ne $null){ - $running - } - else{ - Write-Host "There are no running VMs - probably not a good thing."` - " Fix it." -ForegroundColor White -BackgroundColor Black - } - #--------------------------------------------------------------------- - Write-Host "`n" - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - Write-Host "NOT RUNNING VMs" -ForegroundColor Red ` - -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - $notrunning = Get-VM | where {$_.state -ne 'running'} | ft -AutoSize - if($notrunning -ne $null){ - $notrunning - } - else{ - Write-Host "All VMs are currently running - HOORAY!" ` - -ForegroundColor White -BackgroundColor Black - } - #--------------END Get VM Data --------------------- - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - #--------------------------------------------------------------------- - } -} \ No newline at end of file diff --git a/VMs/VHDInfo/Get-SharedVHDs.ps1 b/VMs/VHDInfo/Get-SharedVHDs.ps1 deleted file mode 100644 index 9670b16..0000000 --- a/VMs/VHDInfo/Get-SharedVHDs.ps1 +++ /dev/null @@ -1,129 +0,0 @@ -<# -.Synopsis - For each VM detected every associated VHD/VHDX is checked to determine - if the VHD/VHDX is shared or not -.DESCRIPTION - Identifies all VHDs/VHDXs associated with each VM detected. For each VHD/VHDX it - pulls several pieces of information to display to user. If - SupportPersistentReservations is true, the VHD/VHDX is shared. -.EXAMPLE - Get-SharedVHDs - - Displays SupportPersistentReservations information for each VHD for every VM - discovered. If SupportPersistentReservations is true, the VHD is shared -.OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - 2008R2Clust2 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx - ---------------------------------------------- - Web1 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx - ---------------------------------------------- - VMs are currently utilizing: 48 GB - VMs could POTENTIALLY Utilize: 180 GB - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM VHD information for all detected Hyp nodes: - VMName - SupportPersistentReservations - Path -#> -function Get-SharedVHDs{ - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------------------------------------------------------------- - Foreach($node in $nodes){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - get-vm -ComputerName $node.name | Get-VMHardDiskDrive | select VMName,` - supportpersistentreservations, path | ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - #--------------------------------------------------------------------- - - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - } - else{ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - $quickCheck = Get-VM | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - #--------------------------------------------------------------------- - get-vm | Get-VMHardDiskDrive | select VMName,` - supportpersistentreservations, path | ft -AutoSize - #--------------------------------------------------------------------- - - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - - } -} \ No newline at end of file diff --git a/VMs/VHDInfo/Get-VMAllVHDs.ps1 b/VMs/VHDInfo/Get-VMAllVHDs.ps1 deleted file mode 100644 index ca15440..0000000 --- a/VMs/VHDInfo/Get-VMAllVHDs.ps1 +++ /dev/null @@ -1,227 +0,0 @@ -<# -.Synopsis - For each VM detected every associated VHD/VHDX is identified and several pieces of - VHD/VHDX information is displayed -.DESCRIPTION - Identifies all VHDs/VHDXs associated with each VM detected. For each VHD/VHDX it - pulls several pieces of information and displays to user. It then - sums the current VHD/VHDX disk usage and the POTENTIAL VHD/VHDX disk usage - dependent on whether the VHDs/VHDXs are fixed are dynamic. -.EXAMPLE - Get-VMAllVHDs - - Displays information for each VHD for every VM discovered -.OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - 2008R2Clust2 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx - ---------------------------------------------- - Web1 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx - ---------------------------------------------- - VMs are currently utilizing: 48 GB - VMs could POTENTIALLY Utilize: 180 GB - ---------------------------------------------- -.NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info -.FUNCTIONALITY - Get the following VM VHD information for all detected Hyp nodes: - VhdType - Size(GB) - MaxSize(GB) - Path - Total current disk usage - Total POTENTIAL disk usage -#> -function Get-VMAllVHDs{ - Write-Host "This will not find any VMs if you are not running PowerShell as "` - "admin!" -ForegroundColor Cyan - #************************Cluster Detection**************************** - $nodes = $null - try{ - $clusterCheck = get-service ClusSvc -ErrorAction SilentlyContinue - if($clusterCheck -ne $null){ - #ok, the cluster service is present, lets see if it is running - $clusterServiceStatus = Get-Service ClusSvc | Select-Object -ExpandProperty Status - if($clusterServiceStatus -eq "Running"){ - $nodes = Get-ClusterNode -ErrorAction SilentlyContinue - if($nodes -eq $null){ - Write-Host "It appears this is a Hyp cluster but no nodes were found -"` - "ensure you are running this in an administratrive PowerShell Window" ` - -ForegroundColor Yellow - return - } - } - else{ - Write-Host "This server has the cluster service but it is not running - "` - "now engaging Standalone diagnostic" -ForegroundColor Cyan - } - } - } - catch{ - Write-Host "There was an error determining if this server is part of a cluster." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "This diagnostic will be executed in standalone mode..." ` - -ForegroundColor Yellow -BackgroundColor Black - } - #***********************End Cluster Detection*************************** - - [int]$currentStorageUse = $null - [int]$potentialStorageUse = $null - [int]$currentS = $null - [int]$potentialS = $null - if($nodes -ne $null){ - #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - #------------------------------------------------------------------------ - Foreach($node in $nodes){ - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - try{ - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if(Test-Connection $node -Count 1 -ErrorAction SilentlyContinue){ - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - $VMs = Get-VM -ComputerName $node.name - foreach($VM in $VMs ){ - #---------for output------------- - Write-Host $vm.VMName -ForegroundColor White ` - -BackgroundColor Black - Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` - ft vhdtype,@{label=’Size(GB)’;` - expression={$_.filesize/1gb –as [int]}},` - @{label=’MaxSize(GB)’;expression={$_.size/1gb –as [int]}},` - path -AutoSize - #------END for output------------ - - #------for storage calc---------- - $cs = $null - $cs = Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` - Select-Object -ExpandProperty Filesize - #account for multiple vhds - $cs2 = $null - foreach($drive in $cs ){ - $cs2 = $cs2 + $drive - } - $ps = $null - $ps = Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` - Select-Object -ExpandProperty Size - #account for multiple vhds - $ps2 = $null - foreach($drive in $ps ){ - $ps2 = $ps2 + $drive - } - #math time - $cs3 = $null - $ps3 = $null - [int64]$cs3 = [convert]::ToInt64($cs2, 10) - [int64]$ps3 = [convert]::ToInt64($ps2, 10) - $cs3 = $cs3/1gb - $ps3 = $ps3/1gb - $currentS = $currentS + $cs3 - $potentialS = $potentialS + $ps3 - #------END for storage calc------ - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - } - else{ - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - } - else{ - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red - } - } - catch{ - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` - -ForegroundColor Red - } - } - #------------------------------------------------------------------------ - $currentStorageUse = $currentS - $potentialStorageUse = $potentialS - Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "VMs could POTENTIALLY Utilize: " $potentialStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #------------------------------------------------------------------------ - } - - else{ - #------------------------------------------------------------------------ - #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - $quickCheck = Get-VM | measure | Select-Object -ExpandProperty count - if($quickCheck -ne 0){ - #--------------------------------------------------------------------- - $VMs=Get-VM - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - foreach($VM in $VMs ){ - #---------for output------------- - Write-Host $vm.VMName -ForegroundColor White -BackgroundColor Black - Get-VHD -VMId $VM.VMId | ft vhdtype,@{label=’Size(GB)’; ` - expression={$_.filesize/1gb –as [int]}},@{label=’MaxSize(GB)’; ` - expression={$_.size/1gb –as [int]}},path -AutoSize - #------END for output------------ - - #------for storage calc---------- - $cs = $null - $cs = Get-VHD -VMId $VM.VMId | Select-Object -ExpandProperty Filesize - #account for multiple vhds - $cs2 = $null - foreach($drive in $cs ){ - $cs2 = $cs2 + $drive - } - $ps = $null - $ps = Get-VHD -VMId $VM.VMId | Select-Object -ExpandProperty Size - #account for multiple vhds - $ps2 = $null - foreach($drive in $ps ){ - $ps2 = $ps2 + $drive - } - #math time - $cs3 = $null - $ps3 = $null - [int64]$cs3 = [convert]::ToInt64($cs2, 10) - [int64]$ps3 = [convert]::ToInt64($ps2, 10) - $cs3 = $cs3/1gb - $ps3 = $ps3/1gb - $currentS = $currentS + $cs3 - $potentialS = $potentialS + $ps3 - #------END for storage calc------ - Write-Host "----------------------------------------------" -ForegroundColor Gray - } - #--------------------------------------------------------------------- - $currentStorageUse = $currentS - $potentialStorageUse = $potentialS - Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "VMs could POTENTIALLY Utilize: " $potentialStorageUse "GB" ` - -ForegroundColor Magenta - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------------------------------------------------------------- - } - else{ - Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black - } - } -} \ No newline at end of file From d1257cfd6256e90327e3c2f0b7e1973824617fda Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Tue, 5 Dec 2017 23:05:23 -0600 Subject: [PATCH 02/15] VM functions and VHD functions have now been converted over to module format. Quite a bit left to convert over for #1 --- Diag-V.psd1 | 1 + Diag-V.psm1 | 89 +++++++++++++++++++++++++++++------------------------ README.md | 2 +- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/Diag-V.psd1 b/Diag-V.psd1 index 0aa96df..3de842e 100644 --- a/Diag-V.psd1 +++ b/Diag-V.psd1 @@ -73,6 +73,7 @@ 'Get-IntegrationServicesCheck', 'Get-BINSpaceInfo', 'Get-VMAllVHDs', + 'Get-SharedVHDs', 'Show-DiagVMenu' ) diff --git a/Diag-V.psm1 b/Diag-V.psm1 index a0801df..c385352 100644 --- a/Diag-V.psm1 +++ b/Diag-V.psm1 @@ -1414,63 +1414,72 @@ function Get-SharedVHDs { param () $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { - if ($nodes -ne $null) { + if ($clusterEval -eq $true) { #we are definitely dealing with a cluster - execute code for cluster - Write-Host "Cluster detected. Executing cluster appropriate diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - #--------------------------------------------------------------------- - Foreach ($node in $nodes) { - Write-Host $node.name -ForegroundColor White -BackgroundColor Black - try { - #lets make sure we can actually reach the other nodes in the cluster - #before trying to pull information from them - if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { - $quickCheck = Get-VM -ComputerName $node.name | measure | ` - Select-Object -ExpandProperty count - if ($quickCheck -ne 0) { - get-vm -ComputerName $node.name | Get-VMHardDiskDrive | select VMName, ` - supportpersistentreservations, path | ft -AutoSize - Write-Host "----------------------------------------------" ` - -ForegroundColor Gray - } - #--------------------------------------------------------------------- - + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Verbose "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + #--------------------------------------------------------------------- + Foreach ($node in $nodes) { + Write-Host $node.name -ForegroundColor White -BackgroundColor Black + try { + #lets make sure we can actually reach the other nodes in the cluster + #before trying to pull information from them + Write-Verbose -Message "Performing connection test to node $node ..." + if (Test-Connection $node -Count 1 -ErrorAction SilentlyContinue) { + Write-Verbose -Message "Connection succesful." + #-----------------Get VM Data Now--------------------- + $quickCheck = Get-VM -ComputerName $node.name | Measure-Object | ` + Select-Object -ExpandProperty count + if ($quickCheck -ne 0) { + get-vm -ComputerName $node.name | Get-VMHardDiskDrive | Select-Object VMName, ` + supportpersistentreservations, path | Format-Table -AutoSize + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + else { + Write-Host "No VMs are present on this node." -ForegroundColor White ` + -BackgroundColor Black + } + #--------------END Get VM Data --------------------- + }#nodeConnectionTest else { - Write-Host "No VMs are present on this node." -ForegroundColor White ` - -BackgroundColor Black - } - } - else { - Write-Host "Node: $node could not be reached - skipping this node" ` - -ForegroundColor Red + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Node: $node could not be reached - skipping this node" ` + -ForegroundColor Red + }#nodeConnectionTest } - } - catch { - Write-Host "ERROR: Could not determine if $node can be reached - skipping this node" ` + catch { + Write-Host "An error was encountered with $node - skipping this node" ` -ForegroundColor Red - } - } - } + Write-Error $_ + } + }#foreachVM + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + }#clusterEval else { #standalone server - execute code for standalone server Write-Host "Standalone server detected. Executing standalone diagnostic..." ` -ForegroundColor Yellow -BackgroundColor Black - $quickCheck = Get-VM | measure | ` + #-----------------Get VM Data Now--------------------- + $quickCheck = Get-VM | Measure-Object | ` Select-Object -ExpandProperty count if ($quickCheck -ne 0) { #--------------------------------------------------------------------- - get-vm | Get-VMHardDiskDrive | select VMName, ` - supportpersistentreservations, path | ft -AutoSize + get-vm | Get-VMHardDiskDrive | Select-Object VMName, ` + supportpersistentreservations, path | Format-Table -AutoSize #--------------------------------------------------------------------- - } else { Write-Host "No VMs are present on this node." -ForegroundColor White ` -BackgroundColor Black } - } + #--------------END Get VM Data --------------------- + }#clusterEval }#administrator check else { Write-Warning -Message "Not running as administrator. No further action can be taken." diff --git a/README.md b/README.md index 30a2694..8ab2c89 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#THIS BRANCH IS NOT PRODUCTION READY AT THIS TIME +# THIS BRANCH IS NOT PRODUCTION READY AT THIS TIME # Diag-V Hyper-V Diagnostic Utility From bf95d7e387af1361c8c973f006a203915772da7e Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Wed, 6 Dec 2017 22:03:06 -0600 Subject: [PATCH 03/15] Further progress on #1 - added Hyper-V allocation function --- Diag-V.psd1 | 1 + Diag-V.psm1 | 1056 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 827 insertions(+), 230 deletions(-) diff --git a/Diag-V.psd1 b/Diag-V.psd1 index 3de842e..56fea38 100644 --- a/Diag-V.psd1 +++ b/Diag-V.psd1 @@ -74,6 +74,7 @@ 'Get-BINSpaceInfo', 'Get-VMAllVHDs', 'Get-SharedVHDs', + 'Test-HyperVAllocation', 'Show-DiagVMenu' ) diff --git a/Diag-V.psm1 b/Diag-V.psm1 index c385352..fba5abc 100644 --- a/Diag-V.psm1 +++ b/Diag-V.psm1 @@ -512,10 +512,10 @@ function Get-VMInfo { foreach ($vhd in $vhds) { $vhdType = $vhd.vhdtype $object | Add-Member -MemberType NoteProperty -name "VHDType-$i" -Value $vhdType -Force - #$vhdSize = $vhd.filesize / 1gb –as [int] + #$vhdSize = $vhd.filesize / 1gb -as [int] [int]$vhdSize = $vhd.filesize / 1gb $object | Add-Member -MemberType NoteProperty -name "VHDSize(GB)-$i" -Value $vhdSize -Force - #$vhdMaxSize = $vhd.size / 1gb –as [int] + #$vhdMaxSize = $vhd.size / 1gb -as [int] [int]$vhdMaxSize = $vhd.size / 1gb $object | Add-Member -MemberType NoteProperty -name "MaxSize(GB)-$i" -Value $vhdMaxSize -Force $i++ @@ -618,10 +618,10 @@ function Get-VMInfo { foreach ($vhd in $vhds) { $vhdType = $vhd.vhdtype $object | Add-Member -MemberType NoteProperty -name "VHDType-$i" -Value $vhdType -Force - #$vhdSize = $vhd.filesize / 1gb –as [int] + #$vhdSize = $vhd.filesize / 1gb -as [int] [int]$vhdSize = $vhd.filesize / 1gb $object | Add-Member -MemberType NoteProperty -name "VHDSize(GB)-$i" -Value $vhdSize -Force - #$vhdMaxSize = $vhd.size / 1gb –as [int] + #$vhdMaxSize = $vhd.size / 1gb -as [int] [int]$vhdMaxSize = $vhd.size / 1gb $object | Add-Member -MemberType NoteProperty -name "MaxSize(GB)-$i" -Value $vhdMaxSize -Force $i++ @@ -1077,7 +1077,7 @@ function Get-BINSpaceInfo { Select-Object -ExpandProperty count if ($quickCheck -ne 0) { $VMInfo = get-vm -computername $node.name - $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' –F ($_.MemoryAssigned / 1GB) } }, ` + $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' -F ($_.MemoryAssigned / 1GB) } }, ` AutomaticStopAction | Format-Table -AutoSize foreach ($vm in $VMInfo) { if ($vm.AutomaticStopAction -eq "Save") { @@ -1122,7 +1122,7 @@ function Get-BINSpaceInfo { $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count if ($quickCheck -ne 0) { $VMInfo = get-vm - $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' –F ($_.MemoryAssigned/1GB) } },` + $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' -F ($_.MemoryAssigned/1GB) } },` AutomaticStopAction | Format-Table -AutoSize foreach ($vm in $VMInfo) { if ($vm.AutomaticStopAction -eq "Save") { @@ -1232,9 +1232,9 @@ function Get-VMAllVHDs { -BackgroundColor Black Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` Format-Table vhdtype, @{label = ’Size(GB)’; ` - expression = {$_.filesize / 1gb –as [int]} + expression = {$_.filesize / 1gb -as [int]} }, ` - @{label = ’MaxSize(GB)’; expression = {$_.size / 1gb –as [int]}}, ` + @{label = ’MaxSize(GB)’; expression = {$_.size / 1gb -as [int]}}, ` path -AutoSize #------END for output------------ @@ -1317,10 +1317,10 @@ function Get-VMAllVHDs { foreach ($VM in $VMs ) { #---------for output------------- Write-Host $vm.VMName -ForegroundColor White -BackgroundColor Black - Get-VHD -VMId $VM.VMId | ft vhdtype, @{label = ’Size(GB)’; ` - expression = {$_.filesize / 1gb –as [int]} + Get-VHD -VMId $VM.VMId | Format-Table vhdtype, @{label = ’Size(GB)’; ` + expression = {$_.filesize / 1gb -as [int]} }, @{label = ’MaxSize(GB)’; ` - expression = {$_.size / 1gb –as [int]} + expression = {$_.size / 1gb -as [int]} }, path -AutoSize #------END for output------------ @@ -1485,6 +1485,602 @@ function Get-SharedVHDs { Write-Warning -Message "Not running as administrator. No further action can be taken." }#administrator check } +<# +.Synopsis + Determines the current resource allocation health of Hyper-V Server or Hyper-V Cluster +.DESCRIPTION + For single Hyper-V instances this function will pull available + CPU and Memory physical resources. It will then tally all VM CPU and memory + allocations and contrast that info with available physical resources + + A cpu ratio higher than 4:1 (vCPU:Logical Processors) will be flagged as bad + A static memory higher than 1:1 will be flagged as bad + There is no best practice published around dynamic maximum memory so the function + will only advise a warning if max memory is higher than available physical memory. + + The same functionality is supported for clustered Hyper-V instances. + The function will poll each node in the cluster and provide info on each node. + The cluster function will also calculate the simulation loss of one node to determine + if VMs could survive and start with one node down. + + Available storage space will also be calculated. For clusters CSV locations will be + checked. For standalone Hyps any drive larger than 10GB and not C: will be checked. + In keeping with best practices anything with less than 20% free space will fail the + health check. +.EXAMPLE + Test-HyperVAllocation + + If executed on a standalone Hyper-V instance it will retrieve CPU/RAM physical resources + If exectured on a Hyper-V cluster it will retrieve CPU/RAM physical resrouces for + all nodes in the cluster and comapares those available resources to resources assigned + to VMs on each Hyper-V instance. +.OUTPUTS + ----------------------------- + SystemName: HYP2 + ----------------------------- + Cores: 24 + Logical Processors: 48 + Total Memory: 256 GB + Free Memory: 248 GB + Number of VMs: 1 + Number of VM Procs: 2 + ----------------------------- + Memory resources are still available: 97 % free + ----------------------------- + Virtual Processors are not overprovisioned 1 : 1 + ----------------------------- + Total Startup memory required for Dynamic VMs: 0 GB + Total Static memory required for Static VMs: 29 GB + ----------------------------- + Total minimum RAM (Startup+Static) required: 29 GB + Minimum RAM: 29 GB does not exceed available RAM: 256 GB + ----------------------------- + VMs would survive a one node failure + Total VM RAM minumum: 56 GB - Total Cluster RAM available with one node down: 256 GB + ----------------------------- + Storage Allocation Information + ----------------------------- + C:\ClusterStorage\Volume2 has the recommended 20% free space. + Free Space: 100 GB + Percent Free: 99.87756 + ----------------------------- +.NOTES + Author: Jake Morrison + TechThoughts - http://techthoughts.info + You can change the CPU ratio cutoff from 4:1 to say 6:1 or 8:1 by editing the + Highlighted section below to suit your requirements +.FUNCTIONALITY + Get the following information for each Hyper-V instance found + System Name + Logical Processors + Total Memory + Free Memory + Total number of VMs + Total number of VM vCPUs + CPU provisioning status + Memory provisioning status + Free space status +#> +function Test-HyperVAllocation { + [CmdletBinding()] + param () + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + Write-Host "Processing pre-checks. This may take a few seconds..." + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + #we are definitely dealing with a cluster - execute code for cluster + Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." + Write-Verbose "Getting all cluster nodes in the cluster..." + $nodes = Get-ClusterNode -ErrorAction SilentlyContinue + if ($nodes -ne $null) { + foreach ($node in $nodes) { + #in order for this function to work we must be able to communicate with all nodes + #lets evaluate good communication to all nodes now + Write-Verbose -Message "Performing connection test to node $node ..." + try { + if (Test-Connection -ComputerName $node -ErrorAction Stop) { + Write-Verbose -Message "Connection succesful." + }#nodeConnectionTest + else { + Write-Verbose -Message "Connection unsuccesful." + Write-Host "Not all nodes could be reached - please address $node" -ForegroundColor Red + return + }#nodeConnectionTest + } + catch { + Write-Host "Error encountered testing connection to cluster nodes:" -ForegroundColor Red + Write-Error $_ + } + }#nodesForEach + #-------------------------------------------------------------------- + #######################CLUSTER DIAG######################## + #-------------------------------------------------------------------- + Write-Verbose -Message "Beginning cluster allocation diagnostics..." + #-------------------------- + $totalClusterRAM = $null + $totalVMClusterRAM = $null + $nodeCount = 0 + #-------------------------- + Foreach ($node in $nodes) { + Write-Verbose -Message "Processing $node" + #-------------------------- + #resets + $w32ProcInfo = $null + $w32OSInfo = $null + $name = $null + $numCores = $null + $numLogicProcs = $null + $totalNumCores = $null + $totalNumLogicProcs = $null + [double]$totalMemory = $null + [double]$freeMemory = $null + $nodeCount += 1 + #--------------------------------------------------------------------- + #get WMI data loaded up + #-------------------------------------------------------------------- + try { + $w32ProcInfo = Get-WmiObject -Namespace "root\cimv2" -Class win32_processor -Impersonation 3 -ComputerName $node -ErrorAction Stop + $w32OSInfo = Get-WmiObject -Namespace "root\cimv2" -Class Win32_OperatingSystem -Impersonation 3 -ComputerName $node -ErrorAction Stop + } + catch { + Write-Host "An error was encountered getting WMI info from $node" -ForegroundColor Red + Write-Error $_ + Return + } + #-------------------------------------------------------------------- + #load specific WMI data into variables + #-------------------------------------------------------------------- + $name = $node + $numCores = $w32ProcInfo.numberOfCores + foreach ($core in $numCores) { + $totalNumCores += $core + } + $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors + foreach ($proc in $numLogicProcs) { + $totalNumLogicProcs += $proc + } + $totalMemory = [math]::Round($w32OSInfo.TotalVisibleMemorySize / 1MB, 0) + #8GB of memory is RESERVED for the host + $availVMMemory = $totalMemory - 8 + $freeMemory = [math]::Round($w32OSInfo.FreePhysicalMemory / 1MB, 0) + $totalClusterRAM += $availVMMemory + #-------------------------------------------------------------------- + #-------------------------------------------------------------------- + #load VM data and count number of VMs and VMs processors + #-------------------------------------------------------------------- + $vms = $null + $vmCount = $null + $vmProcCount = $null + $totalVMProcCount = $null + try { + $vms = Get-VM -ComputerName $node -ErrorAction Stop + $vmCount = $vms | Measure-Object | Select-Object -ExpandProperty count + $vmProcCount = $vms | Get-VMProcessor -ErrorAction Stop | Select-Object -ExpandProperty count + } + catch { + Write-Host "An error was encountered getting VM info from $node" -ForegroundColor Red + Write-Error $_ + Return + } + foreach ($proc in $vmProcCount) { + $totalVMProcCount += $proc + } + #-------------------------------------------------------------------- + #null all counts to permit multiple script runs + #-------------------------------------------------------------------- + $memorystartup = 0 + $MemoryMaximum = 0 + $totalstartupmem = 0 + $totalmaxmem = 0 + $static = 0 + $staticmemory = 0 + #-------------------------------------------------------------------- + #calculate memory usage dynamic/static for each VM to generate totals + #-------------------------------------------------------------------- + try { + foreach ($vm in $vms) { + if ((Get-VMMemory -ComputerName $node -vmname $vm.Name -ErrorAction Stop).DynamicMemoryEnabled -eq "True") { + $memoryStartup = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) + $memoryMaximum = [math]::Round(($VM | select-object MemoryMaximum).memorymaximum / 1GB, 0) + $totalstartupmem += $memoryStartup + $totalmaxmem += $memoryMaximum + } + else { + $static = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) + $staticmemory += $static + } + } + } + catch { + Write-Host "An error was encountered getting VM Memory info from $node" -ForegroundColor Red + Write-Error $_ + Return + } + $totalramrequired = $totalstartupmem + $staticmemory + $totalVMClusterRAM += $totalramrequired + #account for no static and no dynamic situations + if ($totalstartupmem -eq $null) { + $totalstartupmem = 0 + } + if ($staticmemory -eq $null) { + $staticmemory = 0 + } + #-------------------------------------------------------------------- + #output basic information about server + #-------------------------------------------------------------------- + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + Write-Host "SystemName:" $name -ForegroundColor Cyan + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + Write-Host "Cores:" $totalNumCores + Write-Host "Logical Processors:" $totalNumLogicProcs + Write-Host "Total Memory:" $totalMemory GB + Write-Host "Free Memory:" $freeMemory GB "(8GB reserved for Hyper-V Host)" + Write-Host "Avail Memory for VMs: $availVMMemory GB" + Write-Host "Total number of VMs:" $vmCount + Write-Host "Total number of VM vCPUs:" $totalVMProcCount + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + #-------------------------------------------------------------------- + #current memory usage status: + #-------------------------------------------------------------------- + #total memory vs free memory - less than 10% free is considered bad + $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100 + if ($memPercent -lt 10) { + Write-Host "This system is low on memory resources: $memPercent % free" -ForegroundColor Red + } + else { + Write-Host "Memory resources are still available: $memPercent % free" -ForegroundColor Green + } + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + #-------------------------------------------------------------------- + #cpu ratio output + #-------------------------------------------------------------------- + #$vmProcCount = 49 + if ($totalVMProcCount -gt $totalNumLogicProcs) { + $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount) + $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs) + #--------DEFAULT IS 4:1 which is 1/4 = .25------------------------ + if ($cpuRatio -lt .25) { + #adjust above this line to achieve desired ratio------------------ + $procRatio += 1 + Write-Host "Overprovisioned on Virtual processors." $procRatio ": 1" -ForegroundColor Red + } + else { + Write-Host "Virtual Processors not overprovisioned" $procRatio ": 1" -ForegroundColor Green + } + } + else { + Write-Host "Virtual Processors are not overprovisioned 1 : 1" -ForegroundColor Green + } + #-------------------------------------------------------------------- + #memory ratio information + #-------------------------------------------------------------------- + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + write-host "Total Startup memory required for Dynamic VMs: $totalstartupmem GB " + write-host "Total Static memory required for Static VMs: $staticmemory GB " + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + write-host "Total minimum RAM (Startup+Static) required: $totalramrequired GB " + if ($totalramrequired -lt $availVMMemory) { + Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $availVMMemory GB" -ForegroundColor Green + } + elseif ($totalramrequired -eq $availVMMemory){ + Write-Host "Minimum RAM: $totalramrequired GB is exactly at available RAM: $availVMMemory GB" -ForegroundColor Yellow + } + else { + Write-Host "Minimum RAM: $totalramrequired GB exceeds available RAM: $availVMMemory GB" -ForegroundColor Red + } + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + if ($totalmaxmem -ne 0) { + write-host "Total *Potential* Maximum memory for Dynamic VMs: $totalmaxmem GB" + if ($totalmaxmem -lt $availVMMemory) { + Write-Host "Maximum potential RAM: $totalmaxmem GB does not exceed available RAM: $availVMMemory GB" -ForegroundColor Green + } + else { + Write-Host "Maximum potential RAM: $totalmaxmem GB exceeds available RAM: $availVMMemory GB" -ForegroundColor Yellow + } + } + #-------------------------------------------------------------------- + }#nodesForEach + #calculating a node loss and its impact + $x = $totalClusterRAM / $nodeCount + $clusterNodeDownUseable = $totalClusterRAM - $x + if ($totalVMClusterRAM -gt $clusterNodeDownUseable) { + Write-Host "VMs would NOT survive a one node failure" -ForegroundColor Red + Write-Host "Total VM RAM minumum: $totalVMClusterRAM GB - Total Cluster RAM available with one node down: $clusterNodeDownUseable GB" -ForegroundColor Cyan + } + else { + Write-Host "VMs would survive a one node failure" -ForegroundColor Green + Write-Host "Total VM RAM minumum: $totalVMClusterRAM GB - Total Cluster RAM available with one node down: $clusterNodeDownUseable GB" -ForegroundColor Cyan + } + #-------------------------------------------------------------------- + #CSV Storage Space checks - we will check CSV locations only for clustered Hyps + #-------------------------------------------------------------------- + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + Write-Host "Storage Allocation Information" + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + try { + $clusterName = "." + $clusterSharedVolume = Get-ClusterSharedVolume -Cluster $clusterName ` + -ErrorAction SilentlyContinue + if ($clusterSharedVolume -eq $null) { + Write-Host "No CSVs discovered - no storage information pulled" ` + -ForegroundColor Yellow + } + else { + foreach ($volume in $clusterSharedVolume) { + <# + $volumeowner = $volume.OwnerNode.Name + $csvVolume = $volume.SharedVolumeInfo.Partition.Name + $cimSession = New-CimSession -ComputerName $volumeowner + $volumeInfo = Get-Disk -CimSession $cimSession | Get-Partition | ` + Select-Object DiskNumber, @{Name = "Volume"; ` + Expression = {Get-Volume -Partition $_ | ` + Select-Object -ExpandProperty ObjectId} + } + $csvdisknumber = ($volumeinfo | Where-Object ` + { $_.Volume -eq $csvVolume}).Disknumber + #> + $diskName = $volume.SharedVolumeInfo.FriendlyVolumeName + $percentFree = $volume.SharedVolumeInfo.Partition.PercentFree + $spaceFree = [int]($volume.SharedVolumeInfo.Partition.Freespace / 1GB) + #expectations: + #15% For less than 1TB + #10 % For greater than 1TB + $size = [math]::Round($volume.SharedVolumeInfo.partition.Size / 1GB, 0) + $expectations = 20 + if ($size -le 1000) { + $expectations = 15 + } + elseif ($size -gt 1000) { + $expectations = 10 + } + if ($percentFree -lt $expectations) { + Write-Host $diskName "is below the recommended $expectations% free space." -ForegroundColor Red + Write-Host "Total Size: $size GB" -ForegroundColor Gray + Write-Host "Free Space: $spaceFree GB" -ForegroundColor Red + Write-Host "Percent Free: $percentFree" -ForegroundColor Red + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + } + else { + Write-Host $diskName "has the recommended $expectations% free space." -ForegroundColor Green + Write-Host "Total Size: $size GB" -ForegroundColor Gray + Write-Host "Free Space: $spaceFree GB" -ForegroundColor Gray + Write-Host "Percent Free: $percentFree" -ForegroundColor Gray + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + } + } + } + + } + catch { + Write-Host "ERROR - An issue was encountered getting CSVs spacing information:" ` + -ForegroundColor Red + return + } + #-------------------------------------------------------------------- + #######################END CLUSTER DIAG######################## + #-------------------------------------------------------------------- + }#nodeNULLCheck + else { + Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" + }#nodeNULLCheck + }#clusterEval + else { + #standalone server - execute code for standalone server + #######################STANDALONE DIAG######################## + #--------------------------------------------------------------------- + #get WMI data loaded up + #-------------------------------------------------------------------- + try { + $w32ProcInfo = Get-WmiObject -class win32_processor -ErrorAction Stop + $w32OSInfo = Get-WMIObject -class Win32_OperatingSystem -ErrorAction Stop + } + catch { + Write-Host "An error was encountered getting WMI info from $node" -ForegroundColor Red + Write-Error $_ + Return + } + #-------------------------------------------------------------------- + #load specific WMI data into variables + #-------------------------------------------------------------------- + $name = $w32ProcInfo.systemname + $numCores = $w32ProcInfo.numberOfCores + foreach ($core in $numCores) { + $totalNumCores += $core + } + $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors + foreach ($proc in $numLogicProcs) { + $totalNumLogicProcs += $proc + } + $totalMemory = [math]::round($w32OSInfo.TotalVisibleMemorySize / 1MB, 0) + #8GB of memory is RESERVED for the host + $availVMMemory = $totalMemory - 8 + $freeMemory = [math]::round($w32OSInfo.FreePhysicalMemory / 1MB, 0) + #-------------------------------------------------------------------- + #load VM data and count number of VMs and VMs processors + #-------------------------------------------------------------------- + try { + $vms = Get-VM -ErrorAction Stop + $vmCount = $vms | Measure-Object | Select-Object -ExpandProperty count + $vmProcCount = $vms | Get-VMProcessor | Select-Object -ExpandProperty count + } + catch { + Write-Host "An error was encountered getting VM info" -ForegroundColor Red + Write-Error $_ + Return + } + foreach ($proc in $vmProcCount) { + $totalVMProcCount += $proc + } + #-------------------------------------------------------------------- + #null all counts to permit multiple script runs + #-------------------------------------------------------------------- + $memorystartup = 0 + $MemoryMaximum = 0 + $totalstartupmem = 0 + $totalmaxmem = 0 + $static = 0 + $staticmemory = 0 + #-------------------------------------------------------------------- + #calculate memory usage dynamic/static for each VM to generate totals + #-------------------------------------------------------------------- + try { + foreach ($vm in $vms) { + if ((Get-VMMemory -vmname $vm.Name -ErrorAction Stop).DynamicMemoryEnabled -eq "True") { + $memorystartup = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) + $memoryMaximum = [math]::Round(($VM | select-object MemoryMaximum).memorymaximum / 1GB, 0) + + $totalstartupmem += $memoryStartup + $totalmaxmem += $memoryMaximum + } + else { + $static = [math]::Round(($VM | select-object MemoryStartup).MemoryStartup / 1GB, 0) + $staticmemory += $static + } + } + } + catch { + Write-Host "An error was encountered getting VM Memory info from $node" -ForegroundColor Red + Write-Error $_ + Return + } + $totalramrequired = $totalstartupmem + $staticmemory + #account for no static and no dynamic situations + if ($totalstartupmem -eq $null) { + $totalstartupmem = 0 + } + if ($staticmemory -eq $null) { + $staticmemory = 0 + } + #-------------------------------------------------------------------- + #output basic information about server + #-------------------------------------------------------------------- + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + Write-Host "SystemName:" $name -ForegroundColor Cyan + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + Write-Host "Cores:" $totalNumCores + Write-Host "Logical Processors:" $totalNumLogicProcs + Write-Host "Total Memory:" $totalMemory GB + Write-Host "Free Memory:" $freeMemory GB "(8GB reserved for Hyper-V Host)" + Write-Host "Avail Memory for VMs: $availVMMemory GB" + Write-Host "Total number of VMs:" $vmCount + Write-Host "Total number of VM vCPUs:" $totalVMProcCount + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + #-------------------------------------------------------------------- + #current memory usage status: + #-------------------------------------------------------------------- + #total memory vs free memory - less than 10% free is considered bad + $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100 + if ($memPercent -lt 10) { + Write-Host "This system is low on memory resources: $memPercent % free" -ForegroundColor Red + } + else { + Write-Host "Memory resources are still available: $memPercent % free" -ForegroundColor Green + } + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + #-------------------------------------------------------------------- + #cpu ratio output + #-------------------------------------------------------------------- + #$vmProcCount = 49 + if ($totalVMProcCount -gt $totalNumLogicProcs) { + $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount) + $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs) + #$procRatio2 = [math]::round($procRatio / $cpuRatio) + #------------HERE YOU CAN CHANGE CPU RATIO TO DESIRED RATIO------- + #--------DEFAULT IS 4:1 which is 1/4 = .25------------------------ + if ($cpuRatio -lt .25) { + #adjust above this line to achieve desired ratio------------------ + $procRatio += 1 + Write-Host "Overprovisioned on Virtual processors." $procRatio ": 1" -ForegroundColor Red + } + else { + Write-Host "Virtual Processors not overprovisioned" $procRatio ": 1" -ForegroundColor Green + } + } + else { + Write-Host "Virtual Processors are not overprovisioned 1 : 1" -ForegroundColor Green + } + #-------------------------------------------------------------------- + #memory ratio information + #-------------------------------------------------------------------- + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + write-host "Total Startup memory required for Dynamic VMs: $totalstartupmem GB " + write-host "Total Static memory required for Static VMs: $staticmemory GB " + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + write-host "Total minimum RAM (Startup+Static) required: $totalramrequired GB " + if ($totalramrequired -lt $availVMMemory) { + Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $availVMMemory GB" -ForegroundColor Green + } + elseif ($totalramrequired -eq $availVMMemory){ + Write-Host "Minimum RAM: $totalramrequired GB is exactly at available RAM: $availVMMemory GB" -ForegroundColor Yellow + } + else { + Write-Host "Minimum RAM: $totalramrequired GB exceeds available RAM: $availVMMemory GB" -ForegroundColor Red + } + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + if ($totalmaxmem -ne 0) { + write-host "Total *Potential* Maximum memory for Dynamic VMs: $totalmaxmem GB" + if ($totalmaxmem -lt $availVMMemory) { + Write-Host "Maximum potential RAM: $totalmaxmem GB does not exceed available RAM: $availVMMemory GB" -ForegroundColor Green + } + else { + Write-Host "Maximum potential RAM: $totalmaxmem GB exceeds available RAM: $availVMMemory GB" -ForegroundColor Yellow + } + } + #-------------------------------------------------------------------- + #Storage Space checks - we will check all drives greater than 10GB that are no C: + #-------------------------------------------------------------------- + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + Write-Host "Storage Allocation Information" + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + $drives = Get-WmiObject win32_logicaldisk -ErrorAction SilentlyContinue | Where-Object {$_.DeviceID -ne "C:"} + if ($drives -ne $null) { + foreach ($drive in $drives) { + $totalSize = [int]($drive.Size / 1GB) + if ($totalSize -gt 10) { + $driveLetter = $drive.DeviceID + $spaceFree = [int]($drive.Freespace / 1GB) + $percentFree = [math]::round(($spaceFree / $totalSize) * 100) + #expectations: + #15% For less than 1TB + #10 % For greater than 1TB + $size = [math]::Round($drive.Size / 1GB, 0) + $expectations = 20 + if ($size -le 1000) { + $expectations = 15 + } + elseif ($size -gt 1000) { + $expectations = 10 + } + if ($percentFree -lt $expectations) { + Write-Host $driveLetter "is below the recommended $expectations% free space." -ForegroundColor Red + Write-Host "Total Size: $size GB" -ForegroundColor Gray + Write-Host "Free Space: $spaceFree GB" -ForegroundColor Red + Write-Host "Percent Free: $percentFree" -ForegroundColor Red + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + } + else { + Write-Host $driveLetter "has the recommended $expectations% free space." -ForegroundColor Green + Write-Host "Total Size: $size GB" -ForegroundColor Gray + Write-Host "Free Space: $spaceFree GB" -ForegroundColor Gray + Write-Host "Percent Free: $percentFree" -ForegroundColor Gray + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + } + } + } + } + else { + Write-Host "No additional storage other than OS drive deteceted" ` + -ForegroundColor Yellow + } + #######################STANDALONE DIAG######################## + #-------------------------------------------------------------------- + }#clusterEval + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} #endregion @@ -1551,260 +2147,260 @@ function Get-SharedVHDs { ------------------------------ Get-FileSizes #> -function Show-DiagVMenu { - #all this serves to do is to launch the parent menu choice option - showTheTopLevel -} -#################################################################################### -#------------------------------Menu Selections-------------------------------------- -#################################################################################### -<# + function Show-DiagVMenu { + #all this serves to do is to launch the parent menu choice option + showTheTopLevel + } + #################################################################################### + #------------------------------Menu Selections-------------------------------------- + #################################################################################### + <# .Synopsis showTheTopLevel is a menu level function that shows the parent (or top) menu choices .DESCRIPTION showTheTopLevel is a menu level function that shows the parent (or top) menu choices #> -function showTheTopLevel { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " MAIN MENU" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray + function showTheTopLevel { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " MAIN MENU" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] VMs" - Write-Host "[2] VHDs" - Write-Host "[3] Overallocation" - Write-Host "[4] CSVs" - Write-Host "[5] Hyper-V Event Logs" + Write-Host "[1] VMs" + Write-Host "[2] VHDs" + Write-Host "[3] Overallocation" + Write-Host "[4] CSVs" + Write-Host "[5] Hyper-V Event Logs" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - showVMDiags - } - elseif ($topLevel -eq 2) { - showVHDDiags - } - elseif ($topLevel -eq 3) { - showAllocationDiags - } - elseif ($topLevel -eq 4) { - showCSVDiags - } - elseif ($topLevel -eq 5) { - showHyperVLogs - } - else { - Write-Warning "You failed to select one of the available choices" - } -} -<# + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + showVMDiags + } + elseif ($topLevel -eq 2) { + showVHDDiags + } + elseif ($topLevel -eq 3) { + showAllocationDiags + } + elseif ($topLevel -eq 4) { + showCSVDiags + } + elseif ($topLevel -eq 5) { + showHyperVLogs + } + else { + Write-Warning "You failed to select one of the available choices" + } + } + <# .Synopsis showTheTopLevel is a menu level function that shows the VM diagnostic menu choices .DESCRIPTION showTheTopLevel is a menu level function that shows the VM diagnostic menu choices #> -function showVMDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " VM Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Get-VMStatus" - Write-Host "[2] Get-VMInfo" - Write-Host "[3] Get-VMReplicationStatus" - Write-Host "[4] Get-VMLocationPathInfo" - Write-Host "[5] Get-IntegrationServicesCheck" - Write-Host "[6] Get-BINSpaceInfo" - Write-Host "[7] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Get-VMStatus - } - elseif ($topLevel -eq 2) { - Get-VMInfo - } - elseif ($topLevel -eq 3) { - Get-VMReplicationStatus - } - elseif ($topLevel -eq 4) { - Get-VMLocationPathInfo - } - elseif ($topLevel -eq 5) { - Get-IntegrationServicesCheck - } - elseif ($topLevel -eq 6) { - Get-BINSpaceInfo - } - elseif ($topLevel -eq 7) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } -} -<# + function showVMDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " VM Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-VMStatus" + Write-Host "[2] Get-VMInfo" + Write-Host "[3] Get-VMReplicationStatus" + Write-Host "[4] Get-VMLocationPathInfo" + Write-Host "[5] Get-IntegrationServicesCheck" + Write-Host "[6] Get-BINSpaceInfo" + Write-Host "[7] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-VMStatus + } + elseif ($topLevel -eq 2) { + Get-VMInfo + } + elseif ($topLevel -eq 3) { + Get-VMReplicationStatus + } + elseif ($topLevel -eq 4) { + Get-VMLocationPathInfo + } + elseif ($topLevel -eq 5) { + Get-IntegrationServicesCheck + } + elseif ($topLevel -eq 6) { + Get-BINSpaceInfo + } + elseif ($topLevel -eq 7) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } + } + <# .Synopsis showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices .DESCRIPTION showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices #> -function showVHDDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " VHD Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Get-VMAllVHDs" - Write-Host "[2] Get-SharedVHDs" - Write-Host "[3] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Get-VMAllVHDs - } - elseif ($topLevel -eq 2) { - Get-SharedVHDs - } - elseif ($topLevel -eq 3) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } -} -<# + function showVHDDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " VHD Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-VMAllVHDs" + Write-Host "[2] Get-SharedVHDs" + Write-Host "[3] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-VMAllVHDs + } + elseif ($topLevel -eq 2) { + Get-SharedVHDs + } + elseif ($topLevel -eq 3) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } + } + <# .Synopsis showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices .DESCRIPTION showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices #> -function showAllocationDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " OverAllocation Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Test-HyperVAllocation" - Write-Host "[2] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Test-HyperVAllocation - } - elseif ($topLevel -eq 2) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } -} -<# + function showAllocationDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " OverAllocation Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Test-HyperVAllocation" + Write-Host "[2] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Test-HyperVAllocation + } + elseif ($topLevel -eq 2) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } + } + <# .Synopsis showCSVDiags is a menu level function that shows the CSV diagnostic menu choices .DESCRIPTION showCSVDiags is a menu level function that shows the CSV diagnostic menu choices #> -function showCSVDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " CSV Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Get-CSVtoPhysicalDiskMapping" - Write-Host "[2] Get-FileSizes" - Write-Host "[3] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Get-CSVtoPhysicalDiskMapping - } - elseif ($topLevel -eq 2) { - Get-FileSizes - } - elseif ($topLevel -eq 3) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } -} + function showCSVDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " CSV Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-CSVtoPhysicalDiskMapping" + Write-Host "[2] Get-FileSizes" + Write-Host "[3] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-CSVtoPhysicalDiskMapping + } + elseif ($topLevel -eq 2) { + Get-FileSizes + } + elseif ($topLevel -eq 3) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } + } -<# + <# .Synopsis showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices .DESCRIPTION showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices #> -function showHyperVLogs { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " Hyper-V Event Log Search" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Search last 24 hours" - Write-Host "[2] Specify date range" - Write-Host "[3] Main Menu" + function showHyperVLogs { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " Hyper-V Event Log Search" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Search last 24 hours" + Write-Host "[2] Specify date range" + Write-Host "[3] Main Menu" - $MenuChoice = $null - $MenuChoice = Read-Host "Please select a menu number" + $MenuChoice = $null + $MenuChoice = Read-Host "Please select a menu number" - if ($MenuChoice -eq 3) { - showTheTopLevel - } - else { - Get-ClusterCheck - } -} + if ($MenuChoice -eq 3) { + showTheTopLevel + } + else { + Get-ClusterCheck + } + } #################################################################################### #-----------------------------END Menu Selections----------------------------------- From 742837ad14a4ee4dc555e3ee2b969670f8e1ef28 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Wed, 6 Dec 2017 22:33:59 -0600 Subject: [PATCH 04/15] More progress towards #1 - some general cleanup --- Diag-V.psm1 | 549 +++++++++++++++++++++++++++------------------------- 1 file changed, 280 insertions(+), 269 deletions(-) diff --git a/Diag-V.psm1 b/Diag-V.psm1 index fba5abc..501568a 100644 --- a/Diag-V.psm1 +++ b/Diag-V.psm1 @@ -456,7 +456,7 @@ function Get-VMInfo { $vms = get-vm -ComputerName $node.name foreach ($vm in $vms) { Write-Host "----------------------------------------------" ` - -ForegroundColor Gray + -ForegroundColor Gray #_____________________________________________________________ #_____________________________________________________________ $opsName = $null @@ -523,7 +523,7 @@ function Get-VMInfo { $object | Format-List -GroupBy Name }#foreachVM Write-Host "----------------------------------------------" ` - -ForegroundColor Gray + -ForegroundColor Gray ##################################### } else { @@ -563,7 +563,7 @@ function Get-VMInfo { $vms = get-vm foreach ($vm in $vms) { Write-Host "----------------------------------------------" ` - -ForegroundColor Gray + -ForegroundColor Gray #_____________________________________________________________ #_____________________________________________________________ $opsName = $null @@ -629,7 +629,7 @@ function Get-VMInfo { $object | Format-List -GroupBy Name }#foreachVM Write-Host "----------------------------------------------" ` - -ForegroundColor Gray + -ForegroundColor Gray ##################################### } #--------------END Get VM Data --------------------- @@ -1103,10 +1103,10 @@ function Get-BINSpaceInfo { Write-Error $_ } Write-Host "----------------------------------------------" ` - -ForegroundColor Gray + -ForegroundColor Gray }#nodesForEach Write-Host "Total Hard drive space being taken up by BIN files: $vmMemory GB" ` - -ForegroundColor Magenta + -ForegroundColor Magenta Write-Host "----------------------------------------------" ` -ForegroundColor Gray #----------------------------------------------------------------------- @@ -1122,23 +1122,23 @@ function Get-BINSpaceInfo { $quickCheck = Get-VM | Measure-Object | Select-Object -ExpandProperty count if ($quickCheck -ne 0) { $VMInfo = get-vm - $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' -F ($_.MemoryAssigned/1GB) } },` - AutomaticStopAction | Format-Table -AutoSize + $VMInfo | Select-Object VMName, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' -F ($_.MemoryAssigned / 1GB) } }, ` + AutomaticStopAction | Format-Table -AutoSize foreach ($vm in $VMInfo) { if ($vm.AutomaticStopAction -eq "Save") { $vmMemory += [math]::round($vm.MemoryAssigned / 1GB, 0) } } Write-Host "----------------------------------------------" ` - -ForegroundColor Gray + -ForegroundColor Gray Write-Host "Total Hard drive space being taken up by BIN files: $vmMemory GB" ` - -ForegroundColor Magenta + -ForegroundColor Magenta Write-Host "----------------------------------------------" ` - -ForegroundColor Gray + -ForegroundColor Gray } else { Write-Host "No VMs are present on this node." ` - -ForegroundColor White -BackgroundColor Black + -ForegroundColor White -BackgroundColor Black } #--------------END Get VM Data --------------------- }#clusterEval @@ -1164,22 +1164,23 @@ function Get-BINSpaceInfo { Displays information for each VHD for every VM discovered .OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - 2008R2Clust2 + HYP1 + PSHost-1 + + VhdType Size(GB) MaxSize(GB) Path + ------- -------- ----------- ---- + Differencing 10 60 C:\ClusterStorage\Volume1\VMs\VHDs\PSHost-1_A2B10ECE-58EA-474C-A0FA-A66E2104A345.a... + Differencing 33 275 C:\ClusterStorage\volume1\vms\vhds\PSHost_VMs_915F1EA6-1D11-4E6B-A7DC-1C4E30AA0829... - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx - ---------------------------------------------- - Web1 - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx ---------------------------------------------- - VMs are currently utilizing: 48 GB - VMs could POTENTIALLY Utilize: 180 GB + HYP2 + No VMs are present on this node. + ---------------------------------------------- + Total Vhd(x) utilization: + ---------------------------------------------- + VMs are currently utilizing: 43 GB + VMs could POTENTIALLY Utilize: 335 GB ---------------------------------------------- .NOTES Author: Jake Morrison @@ -1231,10 +1232,10 @@ function Get-VMAllVHDs { Write-Host $vm.VMName -ForegroundColor White ` -BackgroundColor Black Get-VHD -ComputerName $node.Name -VMId $VM.VMId | ` - Format-Table vhdtype, @{label = ’Size(GB)’; ` + Format-Table vhdtype, @{label = 'Size(GB)'; ` expression = {$_.filesize / 1gb -as [int]} }, ` - @{label = ’MaxSize(GB)’; expression = {$_.size / 1gb -as [int]}}, ` + @{label = 'MaxSize(GB)'; expression = {$_.size / 1gb -as [int]}}, ` path -AutoSize #------END for output------------ @@ -1283,11 +1284,16 @@ function Get-VMAllVHDs { } catch { Write-Host "An error was encountered with $node - skipping this node" ` - -ForegroundColor Red + -ForegroundColor Red Write-Error $_ } }#foreachVM #------------------------------------------------------------------------ + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host " Total Vhd(x) utilization:" + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray $currentStorageUse = $currentS $potentialStorageUse = $potentialS Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` @@ -1317,9 +1323,9 @@ function Get-VMAllVHDs { foreach ($VM in $VMs ) { #---------for output------------- Write-Host $vm.VMName -ForegroundColor White -BackgroundColor Black - Get-VHD -VMId $VM.VMId | Format-Table vhdtype, @{label = ’Size(GB)’; ` + Get-VHD -VMId $VM.VMId | Format-Table vhdtype, @{label = 'Size(GB)'; ` expression = {$_.filesize / 1gb -as [int]} - }, @{label = ’MaxSize(GB)’; ` + }, @{label = 'MaxSize(GB)'; ` expression = {$_.size / 1gb -as [int]} }, path -AutoSize #------END for output------------ @@ -1352,6 +1358,11 @@ function Get-VMAllVHDs { Write-Host "----------------------------------------------" -ForegroundColor Gray } #--------------------------------------------------------------------- + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host " Total Vhd(x) utilization:" + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray $currentStorageUse = $currentS $potentialStorageUse = $potentialS Write-Host "VMs are currently utilizing: " $currentStorageUse "GB" ` @@ -1452,7 +1463,7 @@ function Get-SharedVHDs { } catch { Write-Host "An error was encountered with $node - skipping this node" ` - -ForegroundColor Red + -ForegroundColor Red Write-Error $_ } }#foreachVM @@ -1463,8 +1474,7 @@ function Get-SharedVHDs { }#clusterEval else { #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." #-----------------Get VM Data Now--------------------- $quickCheck = Get-VM | Measure-Object | ` Select-Object -ExpandProperty count @@ -1763,7 +1773,7 @@ function Test-HyperVAllocation { if ($totalramrequired -lt $availVMMemory) { Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $availVMMemory GB" -ForegroundColor Green } - elseif ($totalramrequired -eq $availVMMemory){ + elseif ($totalramrequired -eq $availVMMemory) { Write-Host "Minimum RAM: $totalramrequired GB is exactly at available RAM: $availVMMemory GB" -ForegroundColor Yellow } else { @@ -1782,6 +1792,9 @@ function Test-HyperVAllocation { #-------------------------------------------------------------------- }#nodesForEach #calculating a node loss and its impact + write-host "----------------------------------------------------------------------" -ForegroundColor Gray + Write-Host "N+1 Allocation Evaluation:" + write-host "----------------------------------------------------------------------" -ForegroundColor Gray $x = $totalClusterRAM / $nodeCount $clusterNodeDownUseable = $totalClusterRAM - $x if ($totalVMClusterRAM -gt $clusterNodeDownUseable) { @@ -2011,7 +2024,7 @@ function Test-HyperVAllocation { if ($totalramrequired -lt $availVMMemory) { Write-Host "Minimum RAM: $totalramrequired GB does not exceed available RAM: $availVMMemory GB" -ForegroundColor Green } - elseif ($totalramrequired -eq $availVMMemory){ + elseif ($totalramrequired -eq $availVMMemory) { Write-Host "Minimum RAM: $totalramrequired GB is exactly at available RAM: $availVMMemory GB" -ForegroundColor Yellow } else { @@ -2095,21 +2108,21 @@ function Test-HyperVAllocation { diagnostic. Each diagnostic is a fully independent function which can be copied and run independent of Diag-V if desired. .EXAMPLE - Diag-V + Show-DiagVMenu - Copy code into an administrative PS or ISE window and run. + .OUTPUTS Output will vary depending on the selected diagnostic. ############################################## - ____ _ __ __ - | _ \(_) __ _ __ _ \ \ / / - | | | | |/ _ |/ _ |____\ \ / / - | |_| | | (_| | (_| |_____\ V / - |____/|_|\__,_|\__, | \_/ - |___/ + ____ _ __ __ + | _ \(_) __ _ __ _ \ \ / / + | | | | |/ _ |/ _ |____\ \ / / + | |_| | | (_| | (_| |_____\ V / + |____/|_|\__,_|\__, | \_/ + |___/ ############################################## - A Hyper-V diagnostic utility + A Hyper-V diagnostic utility ############################################## MAIN MENU ############################################## @@ -2131,8 +2144,6 @@ function Test-HyperVAllocation { ------------------------------ Get-VMLocationPathInfo ------------------------------ - Get-VMDetails - ------------------------------ Get-IntegrationServicesCheck ------------------------------ Get-BINSpaceInfo @@ -2147,260 +2158,260 @@ function Test-HyperVAllocation { ------------------------------ Get-FileSizes #> - function Show-DiagVMenu { - #all this serves to do is to launch the parent menu choice option - showTheTopLevel - } - #################################################################################### - #------------------------------Menu Selections-------------------------------------- - #################################################################################### - <# +function Show-DiagVMenu { + #all this serves to do is to launch the parent menu choice option + showTheTopLevel +} +#################################################################################### +#------------------------------Menu Selections-------------------------------------- +#################################################################################### +<# .Synopsis showTheTopLevel is a menu level function that shows the parent (or top) menu choices .DESCRIPTION showTheTopLevel is a menu level function that shows the parent (or top) menu choices #> - function showTheTopLevel { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " MAIN MENU" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - - Write-Host "[1] VMs" - Write-Host "[2] VHDs" - Write-Host "[3] Overallocation" - Write-Host "[4] CSVs" - Write-Host "[5] Hyper-V Event Logs" - - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - showVMDiags - } - elseif ($topLevel -eq 2) { - showVHDDiags - } - elseif ($topLevel -eq 3) { - showAllocationDiags - } - elseif ($topLevel -eq 4) { - showCSVDiags - } - elseif ($topLevel -eq 5) { - showHyperVLogs - } - else { - Write-Warning "You failed to select one of the available choices" - } - } - <# +function showTheTopLevel { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host " | _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host " | | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host " | |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " MAIN MENU" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + + Write-Host "[1] VMs" + Write-Host "[2] VHDs" + Write-Host "[3] Overallocation" + Write-Host "[4] CSVs" + Write-Host "[5] Hyper-V Event Logs" + + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + showVMDiags + } + elseif ($topLevel -eq 2) { + showVHDDiags + } + elseif ($topLevel -eq 3) { + showAllocationDiags + } + elseif ($topLevel -eq 4) { + showCSVDiags + } + elseif ($topLevel -eq 5) { + showHyperVLogs + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# .Synopsis showTheTopLevel is a menu level function that shows the VM diagnostic menu choices .DESCRIPTION showTheTopLevel is a menu level function that shows the VM diagnostic menu choices #> - function showVMDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " VM Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Get-VMStatus" - Write-Host "[2] Get-VMInfo" - Write-Host "[3] Get-VMReplicationStatus" - Write-Host "[4] Get-VMLocationPathInfo" - Write-Host "[5] Get-IntegrationServicesCheck" - Write-Host "[6] Get-BINSpaceInfo" - Write-Host "[7] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Get-VMStatus - } - elseif ($topLevel -eq 2) { - Get-VMInfo - } - elseif ($topLevel -eq 3) { - Get-VMReplicationStatus - } - elseif ($topLevel -eq 4) { - Get-VMLocationPathInfo - } - elseif ($topLevel -eq 5) { - Get-IntegrationServicesCheck - } - elseif ($topLevel -eq 6) { - Get-BINSpaceInfo - } - elseif ($topLevel -eq 7) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } - } - <# +function showVMDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host " | _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host " | | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host " | |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " VM Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-VMStatus" + Write-Host "[2] Get-VMInfo" + Write-Host "[3] Get-VMReplicationStatus" + Write-Host "[4] Get-VMLocationPathInfo" + Write-Host "[5] Get-IntegrationServicesCheck" + Write-Host "[6] Get-BINSpaceInfo" + Write-Host "[7] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-VMStatus + } + elseif ($topLevel -eq 2) { + Get-VMInfo + } + elseif ($topLevel -eq 3) { + Get-VMReplicationStatus + } + elseif ($topLevel -eq 4) { + Get-VMLocationPathInfo + } + elseif ($topLevel -eq 5) { + Get-IntegrationServicesCheck + } + elseif ($topLevel -eq 6) { + Get-BINSpaceInfo + } + elseif ($topLevel -eq 7) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# .Synopsis showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices .DESCRIPTION showVHDDiags is a menu level function that shows the VHD/VHDX diagnostic menu choices #> - function showVHDDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " VHD Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Get-VMAllVHDs" - Write-Host "[2] Get-SharedVHDs" - Write-Host "[3] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Get-VMAllVHDs - } - elseif ($topLevel -eq 2) { - Get-SharedVHDs - } - elseif ($topLevel -eq 3) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } - } - <# +function showVHDDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host " | _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host " | | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host " | |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " VHD Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-VMAllVHDs" + Write-Host "[2] Get-SharedVHDs" + Write-Host "[3] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-VMAllVHDs + } + elseif ($topLevel -eq 2) { + Get-SharedVHDs + } + elseif ($topLevel -eq 3) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# .Synopsis showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices .DESCRIPTION showAllocationDiags is a menu level function that shows the resource allocation diagnostic menu choices #> - function showAllocationDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " OverAllocation Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Test-HyperVAllocation" - Write-Host "[2] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Test-HyperVAllocation - } - elseif ($topLevel -eq 2) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } - } - <# +function showAllocationDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host " | _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host " | | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host " | |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " OverAllocation Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Test-HyperVAllocation" + Write-Host "[2] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Test-HyperVAllocation + } + elseif ($topLevel -eq 2) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} +<# .Synopsis showCSVDiags is a menu level function that shows the CSV diagnostic menu choices .DESCRIPTION showCSVDiags is a menu level function that shows the CSV diagnostic menu choices #> - function showCSVDiags { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " CSV Diagnostics" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Get-CSVtoPhysicalDiskMapping" - Write-Host "[2] Get-FileSizes" - Write-Host "[3] Main Menu" - $topLevel = $null - $topLevel = Read-Host "Please select a menu number" - if ($topLevel -eq 1) { - Get-CSVtoPhysicalDiskMapping - } - elseif ($topLevel -eq 2) { - Get-FileSizes - } - elseif ($topLevel -eq 3) { - showTheTopLevel - } - else { - Write-Warning "You failed to select one of the available choices" - } - } +function showCSVDiags { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host " | _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host " | | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host " | |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " CSV Diagnostics" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Get-CSVtoPhysicalDiskMapping" + Write-Host "[2] Get-FileSizes" + Write-Host "[3] Main Menu" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" + if ($topLevel -eq 1) { + Get-CSVtoPhysicalDiskMapping + } + elseif ($topLevel -eq 2) { + Get-FileSizes + } + elseif ($topLevel -eq 3) { + showTheTopLevel + } + else { + Write-Warning "You failed to select one of the available choices" + } +} - <# +<# .Synopsis showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices .DESCRIPTION showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices #> - function showHyperVLogs { - Clear-Host - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " ____ _ __ __" -ForegroundColor Cyan - Write-Host "| _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan - Write-Host "| | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan - Write-Host "| |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan - Write-Host "|____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan - Write-Host " |___/ " -ForegroundColor Cyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "A Hyper-V diagnostic utility" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " Hyper-V Event Log Search" -ForegroundColor DarkCyan - Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Search last 24 hours" - Write-Host "[2] Specify date range" - Write-Host "[3] Main Menu" - - $MenuChoice = $null - $MenuChoice = Read-Host "Please select a menu number" - - if ($MenuChoice -eq 3) { - showTheTopLevel - } - else { - Get-ClusterCheck - } - } +function showHyperVLogs { + Clear-Host + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " ____ _ __ __" -ForegroundColor Cyan + Write-Host " | _ \(_) __ _ __ _ \ \ / /" -ForegroundColor Cyan + Write-Host " | | | | |/ _` |/ _` |____\ \ / / " -ForegroundColor Cyan + Write-Host " | |_| | | (_| | (_| |_____\ V / " -ForegroundColor Cyan + Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan + Write-Host " |___/ " -ForegroundColor Cyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host " Hyper-V Event Log Search" -ForegroundColor DarkCyan + Write-Host "##############################################" -ForegroundColor DarkGray + Write-Host "[1] Search last 24 hours" + Write-Host "[2] Specify date range" + Write-Host "[3] Main Menu" + + $MenuChoice = $null + $MenuChoice = Read-Host "Please select a menu number" + + if ($MenuChoice -eq 3) { + showTheTopLevel + } + else { + Get-ClusterCheck + } +} #################################################################################### #-----------------------------END Menu Selections----------------------------------- From 6e9cc8bc6cee2d7645c0b7fe14b96805428ae3e3 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Thu, 7 Dec 2017 15:15:01 -0600 Subject: [PATCH 05/15] Further progress on #1 - allocation and file diagnostics added with other general improvements --- Diag-V.psd1 | 5 +- Diag-V.psm1 | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 257 insertions(+), 8 deletions(-) diff --git a/Diag-V.psd1 b/Diag-V.psd1 index 56fea38..2090996 100644 --- a/Diag-V.psd1 +++ b/Diag-V.psd1 @@ -12,7 +12,7 @@ RootModule = 'Diag-V.psm1' # Version number of this module. - ModuleVersion = '2.0' + ModuleVersion = '1.0' # ID used to uniquely identify this module GUID = 'd0a9150d-b6a4-4b17-a325-e3a24fed0aa9' @@ -70,11 +70,14 @@ 'Get-VMStatus', 'Get-VMInfo', 'Get-VMReplicationStatus', + 'Get-VMLocationPathInfo', 'Get-IntegrationServicesCheck', 'Get-BINSpaceInfo', 'Get-VMAllVHDs', 'Get-SharedVHDs', 'Test-HyperVAllocation', + 'Get-CSVtoPhysicalDiskMapping', + 'Get-FileSizes', 'Show-DiagVMenu' ) diff --git a/Diag-V.psm1 b/Diag-V.psm1 index 501568a..fe4410b 100644 --- a/Diag-V.psm1 +++ b/Diag-V.psm1 @@ -1,3 +1,9 @@ +#region variables + +$Script:version = "1.0" + +#endregion + #region supportingFunctions <# @@ -144,6 +150,8 @@ filter Import-CimXml { #endregion +#region diagnosticFunctions + #region vmDiagnosticFunctions <# @@ -198,6 +206,7 @@ filter Import-CimXml { function Get-VMStatus { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { $clusterEval = Test-IsACluster @@ -428,6 +437,7 @@ function Get-VMStatus { function Get-VMInfo { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { $clusterEval = Test-IsACluster @@ -673,6 +683,7 @@ function Get-VMInfo { function Get-VMReplicationStatus { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { $clusterEval = Test-IsACluster @@ -787,6 +798,7 @@ function Get-VMReplicationStatus { function Get-VMLocationPathInfo { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { $clusterEval = Test-IsACluster @@ -912,6 +924,7 @@ function Get-VMLocationPathInfo { function Get-IntegrationServicesCheck { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { $clusterEval = Test-IsACluster @@ -1053,6 +1066,7 @@ function Get-IntegrationServicesCheck { function Get-BINSpaceInfo { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { $clusterEval = Test-IsACluster @@ -1197,6 +1211,7 @@ function Get-BINSpaceInfo { function Get-VMAllVHDs { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { #--------------------------------- @@ -1423,6 +1438,7 @@ function Get-VMAllVHDs { function Get-SharedVHDs { [CmdletBinding()] param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { if ($clusterEval -eq $true) { @@ -1495,6 +1511,11 @@ function Get-SharedVHDs { Write-Warning -Message "Not running as administrator. No further action can be taken." }#administrator check } + +#endregion + +#region allocationDiagnosticFunctions + <# .Synopsis Determines the current resource allocation health of Hyper-V Server or Hyper-V Cluster @@ -1576,7 +1597,7 @@ function Test-HyperVAllocation { param () $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { - Write-Host "Processing pre-checks. This may take a few seconds..." + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $clusterEval = Test-IsACluster if ($clusterEval -eq $true) { #we are definitely dealing with a cluster - execute code for cluster @@ -2097,6 +2118,231 @@ function Test-HyperVAllocation { #endregion +#region csvFunctions + +<# +.Synopsis + Resolves CSV to a physicalDisk drive +.DESCRIPTION + Discovers all cluster shared volumes associated with the specificed cluster + Resolves all cluster shared volumes to physical drives and pulls usefull + information about the characteristcs of the associated physical drive +.EXAMPLE + Get-CSVtoPhysicalDiskMapping + + This command retrieves all cluster shared volumes and pulls information + related to the physical disk associated with each CSV. Since no cluster name + is specified this command resolves to a locally available cluster (".") +.EXAMPLE + Get-CSVtoPhysicalDiskMappying -clusterName "Clus1.domain.local" + + This command retrieves all cluster shared volumes and pulls information related + to the physical disk associated with the CSVs that are associated with the + Clus1.domain.local cluster. +.OUTPUTS + #CSVName : Cluster Disk 1 + #CSVPartitionNumber : 2 + #Size (GB) : 1500 + #CSVOwnerNode : node1 + #FreeSpace (GB) : 697 + #CSVVolumePath : C:\ClusterStorage\Volume1 + #CSVPhysicalDiskNumber : 3 + #Percent Free : 46.49729 +.NOTES + Adapted from code written by Ravikanth Chaganti http://www.ravichaganti.com + Enhanced by: Jake Morrison - TechThoughts - http://techthoughts.info +.FUNCTIONALITY + Get the following information for each CSV in the cluster: + CSV Name + Total Size of associated physical disk + CSV Volume Path + Percent free of physical disk - VERY useful + CSV Owner Node + CSV Partition Number + Freespace in (GB) +#> +function Get-CSVtoPhysicalDiskMapping { + [cmdletbinding()] + param () + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." + $adminEval = Test-RunningAsAdmin + if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster + if ($clusterEval -eq $true) { + Write-Verbose -Message "Cluster detected. Performing CSV discovery..." + try { + $clusterSharedVolume = Get-ClusterSharedVolume -ErrorAction SilentlyContinue + if ($clusterSharedVolume -eq $null) { + Write-Warning "No CSVs discovered." + } + else { + Write-Verbose -Message "CSVs found. Performing evaluations..." + foreach ($volume in $clusterSharedVolume) { + $volumeowner = $volume.OwnerNode.Name + $csvVolume = $volume.SharedVolumeInfo.Partition.Name + $cimSession = New-CimSession -ComputerName $volumeowner + $volumeInfo = Get-Disk -CimSession $cimSession -ErrorAction Stop ` + | Get-Partition -ErrorAction Stop ` + | Select-Object DiskNumber, @{Name = "Volume"; ` + Expression = {Get-Volume -Partition $_ -ErrorAction Stop ` + | Select-Object -ExpandProperty ObjectId } + } + $csvdisknumber = $null + $csvdisknumber = ($volumeinfo | Where-Object ` + { $_.Volume -eq $csvVolume}).Disknumber + if ($csvdisknumber -eq $null) { + #we can try path instead of ObjectId as a last ditch effort + $volumeInfo = Get-Disk -CimSession $cimSession -ErrorAction Stop ` + | Get-Partition -ErrorAction Stop ` + | Select-Object DiskNumber, @{Name = "Volume"; ` + Expression = {Get-Volume -Partition $_ -ErrorAction Stop ` + | Select-Object -ExpandProperty Path } + } + $csvdisknumber = ($volumeinfo | Where-Object ` + { $_.Volume -eq $csvVolume}).Disknumber + } + $csvtophysicaldisk = New-Object -TypeName PSObject -Property @{ + "CSVName" = $volume.Name + "Size (GB)" = [int]($volume.SharedVolumeInfo.Partition.Size / 1GB) + "CSVVolumePath" = $volume.SharedVolumeInfo.FriendlyVolumeName + "Percent Free" = $volume.SharedVolumeInfo.Partition.PercentFree + "CSVOwnerNode" = $volumeowner + "CSVPhysicalDiskNumber" = $csvdisknumber + "CSVPartitionNumber" = $volume.SharedVolumeInfo.PartitionNumber + "FreeSpace (GB)" = [int]($volume.SharedVolumeInfo.Partition.Freespace / 1GB) + } + $csvtophysicaldisk + } + } + } + catch { + Write-Host "ERROR - An issue was encountered getting physical disks of CSVs:" ` + -ForegroundColor Red + Write-Error $_ + } + }#clusterEval + else { + Write-Warning "No cluster detected. This function is only applicable to clusters with CSVs." + }#clusterEval + }#administrator check + else { + Write-Warning -Message "Not running as administrator. No further action can be taken." + }#administrator check +} + +#endregion + +#region windowsDiagnosticFunctions + +<# +.Synopsis + Scans specified path and gets total size as well as top 10 largest files +.DESCRIPTION + Recursively scans all files in the specified path. It then gives a total + size in GB for all files found under the specified location as well as + the top 10 largest files discovered. The length of scan completion is + impacted by the size of the path specified as well as the number of files +.EXAMPLE + Get-FileSizes -Path C:\ClusterStorage\Volume1\ + + This command recursively scans the specified path and will tally the total + size of all discovered files as well as the top 10 largest files. +.OUTPUTS + Diag-V v1.0 - Processing pre-checks. This may take a few seconds... + Note - depending on how many files are in the path you specified this scan can take some time. Patience please... + Scan results for: C:\ClusterStorage\Volume1\ + ---------------------------------------------- + Total size of all files: 336 GB. + ---------------------------------------------- + Top 10 Largest Files found: + + Directory Name Size(MB) + --------- ---- -------- + C:\ClusterStorage\Volume1\VMs\VHDs PSHost_VMs.vhdx 281604 + C:\ClusterStorage\Volume1\VMs\VHDs PSHost_VMs_915F1EA6-1D11-4E6B-A7DC-1C4E30AA0829.avhdx 33656 + C:\ClusterStorage\Volume1\VMs\VHDs PSHost-1.vhdx 18212 + C:\ClusterStorage\Volume1\VMs\VHDs PSHost-1_A2B10ECE-58EA-474C-A0FA-A66E2104A345.avhdx 10659 + C:\ClusterStorage\Volume1\VMs\PSHost-1\Snapshots 29BFF5A2-3150-4B26-8A64-152193669694.VMRS 0.09 + C:\ClusterStorage\Volume1\VMs\PSHost-1\Virtual Machines 8070AD08-E165-4F8C-B249-6B41DDEEE449.VMRS 0.07 + C:\ClusterStorage\Volume1\VMs\PSHost-1\Virtual Machines 8070AD08-E165-4F8C-B249-6B41DDEEE449.vmcx 0.07 + C:\ClusterStorage\Volume1\VMs\PSHost-1\Snapshots 29BFF5A2-3150-4B26-8A64-152193669694.vmcx 0.05 + PSHost-1 0 + VHDs 0 + + + ---------------------------------------------- +.NOTES + Author: Jake Morrison - TechThoughts - http://techthoughts.info +.FUNCTIONALITY + Get the following information for the specified path: + Total size of all files found under the path + Top 10 largest files discovered +#> +function Get-FileSizes { + [cmdletbinding()] + Param ( + #directory path that you wish to scan + [Parameter(Mandatory = $true, + HelpMessage = "Please enter a path (Ex: C:\ClusterStorage\Volume1)", + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, Position = 0) + ] + [string]$Path + ) + Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." + Write-Host "Note - depending on how many files are in the path you specified"` + "this scan can take some time. Patience please..." -ForegroundColor Gray + #test path and then load location + try { + Write-Verbose -Message "Testing path location..." + if (Test-Path $path -ErrorAction Stop) { + Write-Verbose -Message "Path verified." + Write-Verbose -Message "Getting files..." + $files = Get-ChildItem -Path $path -Recurse -Force ` + -ErrorAction SilentlyContinue + } + else { + Write-Warning "The path you specified is not valid." + return + } + } + catch { + Write-Host "An error was encountered verifying the specified path:" -ForegroundColor Red + Write-Error $_ + } + [double]$intSize = 0 + try { + #get total size of all files + foreach ($objFile in $files) { + $i++ + $intSize = $intSize + $objFile.Length + Write-Progress -activity "Adding File Sizes" -status "Percent added: " ` + -PercentComplete (($i / $files.length) * 100) + } + $intSize = [math]::round($intSize / 1GB, 0) + #generate output + Write-Host "Scan results for: $path" -ForegroundColor Cyan + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host "Total size of all files: $intSize GB." ` + -ForegroundColor Magenta + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + Write-Host "Top 10 Largest Files found:" -ForegroundColor Cyan + $files | Select-Object Directory, Name, @{Label = 'Size(MB)'; Expression = {[math]::round($_.Length / 1MB, 2)}} ` + | Sort-Object 'Size(MB)' -Descending | Select-Object -First 10 | Format-Table -AutoSize + Write-Host "----------------------------------------------" ` + -ForegroundColor Gray + } + catch { + Write-Error $_ + } +} + +#endregion + +#endregion + #region guiMenu <# @@ -2181,7 +2427,7 @@ function showTheTopLevel { Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan Write-Host " |___/ " -ForegroundColor Cyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host " A Hyper-V diagnostic utility - v$Script:version " -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " MAIN MENU" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray @@ -2229,7 +2475,7 @@ function showVMDiags { Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan Write-Host " |___/ " -ForegroundColor Cyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host " A Hyper-V diagnostic utility - v$Script:version " -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " VM Diagnostics" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray @@ -2283,7 +2529,7 @@ function showVHDDiags { Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan Write-Host " |___/ " -ForegroundColor Cyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host " A Hyper-V diagnostic utility - v$Script:version " -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " VHD Diagnostics" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray @@ -2321,7 +2567,7 @@ function showAllocationDiags { Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan Write-Host " |___/ " -ForegroundColor Cyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host " A Hyper-V diagnostic utility - v$Script:version " -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " OverAllocation Diagnostics" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray @@ -2355,7 +2601,7 @@ function showCSVDiags { Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan Write-Host " |___/ " -ForegroundColor Cyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host " A Hyper-V diagnostic utility - v$Script:version " -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " CSV Diagnostics" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray @@ -2394,7 +2640,7 @@ function showHyperVLogs { Write-Host " |____/|_|\__,_|\__, | \_/ " -ForegroundColor Cyan Write-Host " |___/ " -ForegroundColor Cyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " A Hyper-V diagnostic utility" -ForegroundColor DarkCyan + Write-Host " A Hyper-V diagnostic utility - v$Script:version " -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " Hyper-V Event Log Search" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray From 9c8e8c3ddbfbbfdd6a2cb2724f16bfbeec83f832 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Thu, 7 Dec 2017 15:35:46 -0600 Subject: [PATCH 06/15] Starting to update README for #1 changes --- README.md | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 8ab2c89..c7e0554 100644 --- a/README.md +++ b/README.md @@ -4,44 +4,42 @@ Hyper-V Diagnostic Utility ### Synopsis - Collection of several Hyper-V diagnostics that can be run via a simple choice menu. ### Description +Diag-V is a PowerShell Module collection of primarily Hyper-V diagnostic functions, as well as several windows diagnostic functions useful when interacting with Hyper-V servers. -Diag-V is a collection of various Hyper-V diagnostics. It presents the user a simple choice menu that allows the user to select and execute the desired diagnostic. All diagnostics are contained within the Diag-V.ps1 file. Each diagnostic is also broken out into individual functions if you wish to interact with them independently. Each function has a corresponding .ps1 file that you can run independently of Diag-V. +With the module imported diagnostics can be run via the desired function name, alternatively, Diag-V can also present a simple choice menu that enables you to browse via console all diagnostics and execute the desired choice. ### Prerequisites -PowerShell 4 -Administrative PowerShell or ISE window +* Designed and tested on Server 2012R2 and Server 2016 Hyper-V servers running PowerShell 5.1 + * Most functions should work with PowerShell 4 +* Diag-V must be run as a user that has local administrator rights on the Hyper-V server +* If running diagnostics that interact with all cluster nodes Diag-V must be run as a user that has local administrator right to all members of the cluster ### How to run - -1. Copy all code into an administrative ISE window and run. - Alternatively - save the Diag-V.ps1 and run from an administrative PowerShell console window. -2. Selection menu will automatically come up +1. +2. 3. Type in number to select desired diagnostic and execute ### Updates -04 Dec - -Improved Cluster detection error control - -Re-ordered the code of the diagnostics - -Improved comments and documentation - -02 Dec - -Fixed error where RAM was not being tallied properly - -Added code to allow diagnostics to run correctly on VMM platforms +* **?? December 2017** + * TBD +* **04 Dec 2015** + * Improved Cluster detection error control + * Re-ordered the code of the diagnostics + * Improved comments and documentation +* **02 Dec 2015** + * Fixed error where RAM was not being tallied properly + * Added code to allow diagnostics to run correctly on VMM platforms ### Contributors +**Authors:** -Authors: Jake Morrison -Contributors: Marco-Antonio Cervantez +* Jake Morrison - Tech Thoughts - http://techthoughts.info -### Notes +**Contributors:** +* Marco-Antonio Cervantez +* Dillon Childers -You must run Diag-V as an domain user that has privelages for all Cluster nodes if you expect Diag-V to return results from all nodes in the cluster. \ No newline at end of file +### Notes From 7e88e7edef598bf983801a5d4569720689eb3d23 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Fri, 8 Dec 2017 01:19:00 -0600 Subject: [PATCH 07/15] More progress on #1 - particularly proud of this commit with a pretty solid Hyper-V log parser function added --- Diag-V.psd1 | 1 + Diag-V.psm1 | 232 ++++++++++++++++++++++++++++++++++++++++++++++++---- README.md | 7 +- 3 files changed, 217 insertions(+), 23 deletions(-) diff --git a/Diag-V.psd1 b/Diag-V.psd1 index 2090996..e7ceb30 100644 --- a/Diag-V.psd1 +++ b/Diag-V.psd1 @@ -78,6 +78,7 @@ 'Test-HyperVAllocation', 'Get-CSVtoPhysicalDiskMapping', 'Get-FileSizes', + 'Get-HyperVLogs', 'Show-DiagVMenu' ) diff --git a/Diag-V.psm1 b/Diag-V.psm1 index fe4410b..2591f85 100644 --- a/Diag-V.psm1 +++ b/Diag-V.psm1 @@ -17,6 +17,8 @@ $Script:version = "1.0" Returns boolean if local device is part of a cluster .OUTPUTS Boolean value +.COMPONENT + Diag-V .NOTES Author: Jake Morrison http://techthoughts.info @@ -90,6 +92,8 @@ function Test-IsACluster { This will verify if the current PowerShell session is running under the context of an Administrator .OUTPUTS Boolean value +.COMPONENT + Diag-V .NOTES Author: Jake Morrison http://techthoughts.info @@ -189,6 +193,8 @@ filter Import-CimXml { HYP2 No VMs are present on this node. ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -416,6 +422,8 @@ function Get-VMStatus { HYP2 No VMs are present on this node. ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -667,7 +675,9 @@ function Get-VMInfo { ARK_DHCP Operating normally Replicating Normal Primary ARK_MGMT_MDT Operating normally Replicating Normal Primary ARK_WDS Operating normally Replicating Normal Primary - ARKWSUS Operating normally Replicating Normal Primary + ARKWSUS Operating normally Replicating Normal Primary +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -782,6 +792,8 @@ function Get-VMReplicationStatus { SnapshotFileLocation : \\sofs-csv\VMs\2008R2Clust SmartPagingFilePath : \\sofs-csv\VMs\2008R2Clust ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -912,6 +924,8 @@ function Get-VMLocationPathInfo { ---------------------------------------------- TestLinux2 - no integration services installed ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -1053,6 +1067,8 @@ function Get-IntegrationServicesCheck { Total Hard drive space being taken up by BIN files: GB ---------------------------------------------- ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -1196,6 +1212,8 @@ function Get-BINSpaceInfo { VMs are currently utilizing: 43 GB VMs could POTENTIALLY Utilize: 335 GB ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -1426,6 +1444,8 @@ function Get-VMAllVHDs { VMs are currently utilizing: 48 GB VMs could POTENTIALLY Utilize: 180 GB ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -1575,6 +1595,8 @@ function Get-SharedVHDs { Free Space: 100 GB Percent Free: 99.87756 ----------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -2148,6 +2170,8 @@ function Test-HyperVAllocation { #CSVVolumePath : C:\ClusterStorage\Volume1 #CSVPhysicalDiskNumber : 3 #Percent Free : 46.49729 +.COMPONENT + Diag-V .NOTES Adapted from code written by Ravikanth Chaganti http://www.ravichaganti.com Enhanced by: Jake Morrison - TechThoughts - http://techthoughts.info @@ -2271,6 +2295,8 @@ function Get-CSVtoPhysicalDiskMapping { ---------------------------------------------- +.COMPONENT + Diag-V .NOTES Author: Jake Morrison - TechThoughts - http://techthoughts.info .FUNCTIONALITY @@ -2338,6 +2364,165 @@ function Get-FileSizes { Write-Error $_ } } +<# +.Synopsis + Parses Hyper-V event logs and retrieves log entries based on user provided options +.DESCRIPTION + Scans Hyper-V server for all Hyper-V Event Logs and then filters by user provided options. This functions serves merely to craft the appropriate syntax for + Get-WinEvent to retrieve the desired Hyper-V log results. +.PARAMETER LastMinutes + The # of minutes back in time you wish to retrieve Hyper-V logs. Ex: 90 - this would retrieve the last 90 minutes of Hyper-V logs. If this parameter is specified StartDate and EndDate cannot be used. +.PARAMETER StartDate + The initial date that logs should be retrieved from. Ex: MM/DD/YY (12/07/17 - December 07, 2017). If this parameter is specified LastMinutes cannot be used. +.PARAMETER EndDate + The end date that logs should be retrieved from. Ex: MM/DD/YY (12/07/17 - December 07, 2017). If this parameter is specified LastMinutes cannot be used. +.PARAMETER Newest + Specifies the number of latest log entries to retrieve. Ex: 5 - this would retrieve the latest 5 entries +.PARAMETER FilterText + Wild card string to search logs for. Log data will only be returned that contains this wild card string. Ex: Switch - this would retrieve entries that contain the word switch +.PARAMETER WarningErrorCritical + If this switch is used only Warning, Error, Critical log data will be returned. +.EXAMPLE + Get-HyperVLogs + + Retrieves all available Hyper-V logs from the server. +.EXAMPLE + Get-HyperVLogs -Newest 15 -Verbose + + Retrieves the most recent 15 log entries from all available Hyper-V logs on the server with verbose output. +.EXAMPLE + Get-HyperVLogs -FilterText Switch -Newest 2 -ErrorsOnly -Verbose + + Retrieves the most recent 2 Hyper-V log entries that are Warning/Error/Critical that contain the word switch +.EXAMPLE + Get-HyperVLogs -StartDate 11/01/17 -ErrorsOnly + + Retrieves all Warning/Error/Critical Hyper-V log entries from November 1, 2017 to current date +.EXAMPLE + Get-HyperVLogs -StartDate 11/01/17 -EndDate 12/01/17 + + Retrieves all Hyper-V log entries from November 1, 2017 to December 1, 2017 +.EXAMPLE + Get-HyperVLogs -LastMinutes 90 -Newest 20 -FilterText Switch + + Retrieves all Hyper-V logs from the last 90 minutes, returns the newest 20 that contains the word switch +.OUTPUTS + ProviderName: Microsoft-Windows-Hyper-V-VMMS + + TimeCreated Id ProviderName LevelDisplayName Message + ----------- -- ------------ ---------------- ------- + 12/07/17 12:06:16 26002 Microsoft-Windows-Hyper-V-VMMS Information Switch deleted, name='C14EF845-E76A-4318-BE31-F0FB0739B9A4', friendly name='External'. + 12/07/17 12:06:16 26018 Microsoft-Windows-Hyper-V-VMMS Information External ethernet port '{4BB35159-FECD-4845-BD69-39C9770913AB}' unbound. + 12/07/17 12:06:16 26078 Microsoft-Windows-Hyper-V-VMMS Information Ethernet switch port disconnected (switch name = 'C14EF845-E76A-4318-BE31-F0FB0739B9A4', port name = '6B818751-EC33-407C-BCD2-A4FA7F7C31FA'). + 12/07/17 12:06:16 26026 Microsoft-Windows-Hyper-V-VMMS Information Internal miniport deleted, name = '6BC4B864-27B7-4D1A-AD05-CF552FA8E9D0', friendly name = 'External'. + 12/07/17 12:06:15 26078 Microsoft-Windows-Hyper-V-VMMS Information Ethernet switch port disconnected (switch name = 'C14EF845-E76A-4318-BE31-F0FB0739B9A4', port name = '7BF33E31-7676-4344-B168-D9EDB49BBBB6'). + 12/07/17 12:06:02 26142 Microsoft-Windows-Hyper-V-VMMS Error Failed while removing virtual Ethernet switch. + 12/07/17 12:06:02 26094 Microsoft-Windows-Hyper-V-VMMS Error The automatic Internet Connection Sharing switch cannot be modified. + 12/07/17 12:05:11 26002 Microsoft-Windows-Hyper-V-VMMS Information Switch deleted, name='CA2A6472-F6C5-4C6C-84BD-06489F08E4F8', friendly name='Internal'. +.COMPONENT + Diag-V +.NOTES + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Contributor: Dillon Childers + Name Value + ---- ----- + Verbose 5 + Informational 4 + Warning 3 + Error 2 + Critical 1 + LogAlways 0 +.FUNCTIONALITY + Retrieves Hyper-V Event Logs information +#> +function Get-HyperVLogs { + [cmdletbinding(DefaultParameterSetName = ’All’)] + param + ( + [Parameter(Mandatory = $false, ParameterSetName = 'Time')] + [int]$LastMinutes, + [Parameter(Mandatory = $false, ParameterSetName = 'Time2')] + [datetime]$StartDate, + [Parameter(Mandatory = $false, ParameterSetName = 'Time2')] + [datetime]$EndDate, + [Parameter(Mandatory = $false, ParameterSetName = 'All')] + [Parameter(ParameterSetName = 'Time')] + [Parameter(ParameterSetName = 'Time2')] + [int]$Newest = 0, + [Parameter(Mandatory = $false, ParameterSetName = 'All')] + [Parameter(ParameterSetName = 'Time')] + [Parameter(ParameterSetName = 'Time2')] + [string]$FilterText = "", + [Parameter(Mandatory = $false, ParameterSetName = 'All')] + [Parameter(ParameterSetName = 'Time')] + [Parameter(ParameterSetName = 'Time2')] + [switch]$WarningErrorCritical + ) + #default to include all log levels + $level = 0, 1, 2, 3, 4, 5 + #------------------------------------------------------------------ + #we need to get the date, things don't work very well if we cannot do this. + try { + [datetime]$theNow = Get-Date -ErrorAction Stop + if ($LastMinutes -eq $null -or $LastMinutes -eq 0) { + if ($StartDate -eq $null) { + #if user doesn't provide a startdate we will default to 30 days back + $StartDate = $theNow.AddDays(-30) + } + if ($EndDate -eq $null) { + #if user doesn't provide an endate we will use the endate of today + $EndDate = $theNow + } + }#lastminutesEval + else { + #the user has chosen to go back in time by a set number of minutes + $StartDate = $theNow.AddMinutes( - $LastMinutes) + $EndDate = $theNow + }#lastminutesEval + if ($WarningErrorCritical) { + $level = 1, 2, 3 + }#WarningErrorCritical + } + catch { + Write-Warning "Unable to get the current date on this device:" + Write-Error $_ + } + #------------------------------------------------------------------ + Write-Verbose -Message "NOW: $theNow" + Write-Verbose -Message "Start: $StartDate" + Write-Verbose -Message "End: $EndDate" + #------------------------------------------------------------------ + #create filter hashtable + $filter = @{ + LogName = "*Hyper-v*" + Level = $level + StartTime = $StartDate + EndTime = $EndDate + } + #------------------------------------------------------------------ + #different calls are made depending on use choice + if ($FilterText -ne "" -and $Newest -ne 0) { + Write-Verbose -Message "Get-WinEvent -FilterHashTable $filter | Where-Object -Property Message -like ""*$FilterText*"" | Select-Object -First $Newest" + $logs = Get-WinEvent -FilterHashTable $filter -ErrorAction SilentlyContinue | Where-Object -Property Message -like "*$FilterText*" | Select-Object -First $Newest | Select-Object TimeCreated, Id, ProviderName, LevelDisplayName, Message | Format-Table -GroupBy ProviderName + } + elseif ($FilterText -eq "" -and $Newest -ne 0) { + Write-Verbose -Message "Get-WinEvent -FilterHashTable $filter | Select-Object -First $Newest " + $logs = Get-WinEvent -FilterHashTable $filter -ErrorAction SilentlyContinue | Select-Object -First $Newest | Select-Object TimeCreated, Id, ProviderName, LevelDisplayName, Message | Format-Table -GroupBy ProviderName + } + elseif ($Newest -eq 0 -and $FilterText -ne "") { + Write-Verbose -Message "Get-WinEvent -FilterHashTable $filter | Where-Object -Property Message -like ""*$FilterText*""" + $logs = Get-WinEvent -FilterHashTable $filter -ErrorAction SilentlyContinue | Where-Object -Property Message -like "*$FilterText*" | Select-Object TimeCreated, Id, ProviderName, LevelDisplayName, Message | Format-Table -GroupBy ProviderName + } + else { + Write-Verbose -Message "Get-WinEvent -FilterHashTable $filter" + $logs = Get-WinEvent -FilterHashTable $filter -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, ProviderName, LevelDisplayName, Message | Format-Table -GroupBy ProviderName + } + if ($logs -eq $null) { + Write-Warning "No logs entries were found that matched the provided criteria." + } + #------------------------------------------------------------------ + return $logs +} #endregion @@ -2378,6 +2563,8 @@ function Get-FileSizes { [4] CSVs [5] Hyper-V Event Logs Please select a menu number: +.COMPONENT + Diag-V .NOTES Author: Jake Morrison TechThoughts - http://techthoughts.info @@ -2436,7 +2623,7 @@ function showTheTopLevel { Write-Host "[2] VHDs" Write-Host "[3] Overallocation" Write-Host "[4] CSVs" - Write-Host "[5] Hyper-V Event Logs" + Write-Host "[5] Basic Diagnostics" $topLevel = $null $topLevel = Read-Host "Please select a menu number" @@ -2453,7 +2640,7 @@ function showTheTopLevel { showCSVDiags } elseif ($topLevel -eq 5) { - showHyperVLogs + showBasicDiags } else { Write-Warning "You failed to select one of the available choices" @@ -2606,17 +2793,13 @@ function showCSVDiags { Write-Host " CSV Diagnostics" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray Write-Host "[1] Get-CSVtoPhysicalDiskMapping" - Write-Host "[2] Get-FileSizes" - Write-Host "[3] Main Menu" + Write-Host "[2] Main Menu" $topLevel = $null $topLevel = Read-Host "Please select a menu number" if ($topLevel -eq 1) { Get-CSVtoPhysicalDiskMapping } elseif ($topLevel -eq 2) { - Get-FileSizes - } - elseif ($topLevel -eq 3) { showTheTopLevel } else { @@ -2626,11 +2809,11 @@ function showCSVDiags { <# .Synopsis - showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices + showBasicDiags is a menu level function that shows the basic diagnostic menu choices .DESCRIPTION - showHyperVLogs is a menu level function that shows the Hyper-V Event Log menu choices + showBasicDiags is a menu level function that shows the basic diagnostic menu choices #> -function showHyperVLogs { +function showBasicDiags { Clear-Host Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " ____ _ __ __" -ForegroundColor Cyan @@ -2642,20 +2825,33 @@ function showHyperVLogs { Write-Host "##############################################" -ForegroundColor DarkGray Write-Host " A Hyper-V diagnostic utility - v$Script:version " -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host " Hyper-V Event Log Search" -ForegroundColor DarkCyan + Write-Host " Basic Diagnostics" -ForegroundColor DarkCyan Write-Host "##############################################" -ForegroundColor DarkGray - Write-Host "[1] Search last 24 hours" - Write-Host "[2] Specify date range" + Write-Host "[1] Get-HyperVLogs" + Write-Host "[2] Get-FileSizes" Write-Host "[3] Main Menu" - $MenuChoice = $null - $MenuChoice = Read-Host "Please select a menu number" + $topLevel = $null + $topLevel = Read-Host "Please select a menu number" - if ($MenuChoice -eq 3) { + if ($topLevel -eq 1) { + Write-Host "Get-HyperVLogs function requires several parameters that you must specify. This text menu is not able to launch it." -ForegroundColor DarkCyan + Write-Host "Here are a few examples:" -ForegroundColor DarkCyan + Write-Host "Get-HyperVLogs" -ForegroundColor Cyan + Write-Host "Get-HyperVLogs -Newest 15 -Verbose" -ForegroundColor Cyan + Write-Host "Get-HyperVLogs -FilterText Switch -Newest 2 -ErrorsOnly -Verbose" -ForegroundColor Cyan + Write-Host "Get-HyperVLogs -StartDate 11/01/17 -ErrorsOnly" -ForegroundColor Cyan + Write-Host "Get-HyperVLogs -StartDate 11/01/17 -EndDate 12/01/17" -ForegroundColor Cyan + Write-Host "Get-HyperVLogs -LastMinutes 90 -Newest 20 -FilterText Switch" -ForegroundColor Cyan + } + elseif ($topLevel -eq 2) { + Get-FileSizes + } + elseif ($MenuChoice -eq 3) { showTheTopLevel } else { - Get-ClusterCheck + Write-Warning "You failed to select one of the available choices" } } diff --git a/README.md b/README.md index c7e0554..f943205 100644 --- a/README.md +++ b/README.md @@ -33,12 +33,9 @@ With the module imported diagnostics can be run via the desired function name, a * Fixed error where RAM was not being tallied properly * Added code to allow diagnostics to run correctly on VMM platforms +### Author +Jake Morrison - Tech Thoughts - http://techthoughts.info ### Contributors -**Authors:** - -* Jake Morrison - Tech Thoughts - http://techthoughts.info - -**Contributors:** * Marco-Antonio Cervantez * Dillon Childers From b1be9264781e63182faeea04349d6b62d087fb5b Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Dec 2017 00:12:12 -0600 Subject: [PATCH 08/15] First RC for #1 - code review completed. Testing completed. Minor bug fixes and documentation more fully fleshed out --- Diag-V.psd1 | 8 +- Diag-V.psm1 | 344 +++++++++++++++++++++++++++++----------------------- README.md | 68 ++++++++--- 3 files changed, 250 insertions(+), 170 deletions(-) diff --git a/Diag-V.psd1 b/Diag-V.psd1 index e7ceb30..dca6718 100644 --- a/Diag-V.psd1 +++ b/Diag-V.psd1 @@ -3,7 +3,7 @@ # # Generated by: Jake Morrison # -# Generated on: 1/24/2012 +# Generated on: 12/10/2017 # @{ @@ -24,13 +24,13 @@ CompanyName = 'Tech Thoughts' # Copyright statement for this module - Copyright = '(c) 2018 Jacob Morrison. All rights reserved.' + Copyright = '(c) 2017-2018 Jacob Morrison. All rights reserved.' # Description of the functionality provided by this module - # Description = '' + Description = 'A Hyper-V Diagnostic Utility' # Minimum version of the Windows PowerShell engine required by this module - # PowerShellVersion = '' + PowerShellVersion = '4.0' # Name of the Windows PowerShell host required by this module # PowerShellHostName = '' diff --git a/Diag-V.psm1 b/Diag-V.psm1 index 2591f85..833d4be 100644 --- a/Diag-V.psm1 +++ b/Diag-V.psm1 @@ -8,22 +8,25 @@ $Script:version = "1.0" <# .Synopsis - Evaluates if local device is a member of a cluster or a standalone server + Evaluates if local device is a member of a cluster or a standalone server .DESCRIPTION - Evaluates several factors to determine if device is a member of a cluster or acting as a standalone server. The cluster service is evaluated, and if present the cluster nodes will be tested to determine if the local device is a member. If the cluster service is not running the cluster registry location is evaluated to determine if the server's cluster membership status. + Evaluates several factors to determine if device is a member of a cluster or acting as a standalone server. + The cluster service is evaluated, and if present the cluster nodes will be tested to determine if the local + device is a member. If the cluster service is not running the cluster registry location is evaluated to + determine if the server's cluster membership status. .EXAMPLE Test-IsACluster Returns boolean if local device is part of a cluster .OUTPUTS - Boolean value + Boolean value .COMPONENT Diag-V .NOTES - Author: Jake Morrison - http://techthoughts.info - - The design of this function intends the function to be run on the device that is being evaluated + Author: Jake Morrison - TechThoughts - http://techthoughts.info + The design of this function intends the function to be run on the device that is being evaluated +.FUNCTIONALITY + Tests if device is standalone or part of a cluster #> function Test-IsACluster { [CmdletBinding()] @@ -55,7 +58,7 @@ function Test-IsACluster { } Write-Verbose -Message "Cluster node evaulation complete." } - } + }#clusterServiceRunning else { Write-Verbose -Message "Cluster service is not running. Cluster cmdlets not possible. Switching to registry evaluation..." $clusterRegistryPath = "HKLM:\SYSTEM\CurrentControlSet\Services\ClusSvc\Parameters" @@ -69,11 +72,11 @@ function Test-IsACluster { Write-Verbose -Message "Hostname was not found in cluster registry settings." } } - } - } + }#clusterServiceRunning + }#clusterServiceCheck else { Write-Verbose -Message "No cluster service was found." - } + }#clusterServiceCheck } catch { Write-Verbose -Message "There was an error determining if this server is part of a cluster." @@ -83,20 +86,21 @@ function Test-IsACluster { } <# .Synopsis - Tests if PowerShell Session is running as Admin + Tests if PowerShell Session is running as Admin .DESCRIPTION - Evaluates if current PowerShell session is running under the context of an Administrator + Evaluates if current PowerShell session is running under the context of an Administrator .EXAMPLE Test-RunningAsAdmin This will verify if the current PowerShell session is running under the context of an Administrator .OUTPUTS - Boolean value + Boolean value .COMPONENT Diag-V .NOTES - Author: Jake Morrison - http://techthoughts.info + Author: Jake Morrison - TechThoughts - http://techthoughts.info +.FUNCTIONALITY + Evaluates if PowerShell session is running as Administrator and returns true/false based on finding #> function Test-RunningAsAdmin { [CmdletBinding()] @@ -124,9 +128,6 @@ function Test-RunningAsAdmin { Import-CimXml iterates through INSTANCE/PROPERTY data to find the desired information .DESCRIPTION Import-CimXml iterates through INSTANCE/PROPERTY data to find the desired information -.EXAMPLE - - .OUTPUTS Custom object return .NOTES @@ -160,7 +161,7 @@ filter Import-CimXml { <# .Synopsis - Name, State, CPUUsage, Memory usage, Uptime, and Status of all VMs on a cluster or standalone hyp + Displays status for all VMs on a standalone Hyper-V server or Hyper-V cluster .DESCRIPTION Gets the status of all discovered VMs. Automatically detects if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM status information for all VMs on the hyp. If a cluster is detected it will display VM status information for each node in the cluster. .EXAMPLE @@ -196,11 +197,12 @@ filter Import-CimXml { .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - it will automatically detect standalone or cluster and will run the appropriate diagnostic + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: + Gets the following VM information for all detected Hyp nodes: Name State CPUUsage @@ -324,13 +326,12 @@ function Get-VMStatus { -ForegroundColor Red Write-Error $_ } - } + }#nodesForEach #------------------------------------------------------------------------ }#nodeNULLCheck else { Write-Warning -Message "Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode" }#nodeNULLCheck - }#cluster eval else { #standalone server - execute code for standalone server @@ -387,47 +388,45 @@ function Get-VMStatus { } <# .Synopsis - Name, CPU, DynamicMemoryEnabled, MemoryMinimum(MB), MemoryMaximum(GB), VHDType, VHDSize, VHDMaxSize cluster or standalone hyp + Retrieves basic and advanced VM information for all VMs found on a standalone or cluster .DESCRIPTION - Gets the VMs configruation info for all VMs. Automatically detects if running on a + Gets the VMs configuration info for all VMs. Automatically detects if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM configuration information for all VMs on the hyp. If a cluster is detected it will - display VM configuration information for each node in the cluster. + display VM configuration information for each node in the cluster. This function goes a + lot further than a simple Get-VM and provides in depth information on the VM configuration. .EXAMPLE Get-VMInfo This command will automatically detect a standalone hyp or hyp cluster and - will retrieve VM configuration information for all detected nodes. + will retrieve VM configuration information for all detected VMs. .OUTPUTS - HYP1 - - Name: PSHost-1 + ---------------------------------------------- + Name: TestVM-1 - Name : PSHost-1 - CPU : 8 - DynamicMemoryEnabled : False + Name : TestVM-1 + CPU : 2 + DynamicMemoryEnabled : True MemoryMinimum(MB) : 1024 - MemoryMaximum(GB) : 24 - VHDType-0 : Differencing - VHDSize(GB)-0 : 10 + MemoryMaximum(GB) : 8 + IsClustered : False + Version : 8.0 + ReplicationHealth : NotApplicable + OS Name : Windows Server 2016 Datacenter + FQDN : WIN-JHKGN3JEA77 + VHDType-0 : Dynamic + VHDSize(GB)-0 : 25 MaxSize(GB)-0 : 60 - VHDType-1 : Differencing - VHDSize(GB)-1 : 33 - MaxSize(GB)-1 : 275 - - - ---------------------------------------------- - HYP2 - No VMs are present on this node. ---------------------------------------------- .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - it will automatically detect standalone or cluster and will run the appropriate diagnostic + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following VM information for all detected Hyp nodes: Name @@ -436,8 +435,10 @@ function Get-VMStatus { MemoryMinimum(MB) MemoryMaximum(GB) IsClustered + Version ReplicationHealth OSName + FQDN VHDType VHDSize VHDMaxSize @@ -516,7 +517,10 @@ function Get-VMInfo { $clustered = $vm | Select-Object -ExpandProperty IsClustered $object | Add-Member -MemberType NoteProperty -name 'IsClustered' -Value $clustered -Force - + + $vmVersion = $vm | Select-Object -ExpandProperty Version + $object | Add-Member -MemberType NoteProperty -name 'Version' -Value $vmVersion -Force + $repHealth = $vm | Select-Object -ExpandProperty ReplicationHealth $object | Add-Member -MemberType NoteProperty -name 'ReplicationHealth' -Value $repHealth -Force @@ -622,6 +626,9 @@ function Get-VMInfo { $clustered = $vm | Select-Object -ExpandProperty IsClustered $object | Add-Member -MemberType NoteProperty -name 'IsClustered' -Value $clustered -Force + + $vmVersion = $vm | Select-Object -ExpandProperty Version + $object | Add-Member -MemberType NoteProperty -name 'Version' -Value $vmVersion -Force $repHealth = $vm | Select-Object -ExpandProperty ReplicationHealth $object | Add-Member -MemberType NoteProperty -name 'ReplicationHealth' -Value $repHealth -Force @@ -659,9 +666,12 @@ function Get-VMInfo { } <# .Synopsis - Name, Status, ReplicationState, ReplicationHealth, ReplicationMode cluster or standalone hyp + Gets VM replication configuration and replication status for all detected VMs .DESCRIPTION - Gets the VMs replication status info for all VMs. Automatically detects if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM replication status info for all VMs on the hyp. If a cluster is detected it will display VM replication status information for each node in the cluster. + Gets the VMs replication status info for all VMs. Automatically detects if running + on a standalone hyp or hyp cluster. If standalone is detected it will display VM + replication status info for all VMs on the hyp. If a cluster is detected it will + display VM replication status information for each node in the cluster. .EXAMPLE Get-VMReplicationStatus @@ -679,9 +689,10 @@ function Get-VMInfo { .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - it will automatically detect standalone or cluster and will run the appropriate diagnostic + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following VM information for all detected Hyp nodes: Name @@ -745,8 +756,7 @@ function Get-VMReplicationStatus { }#clusterEval else { #standalone server - execute code for standalone server - Write-Host "Standalone server detected. Executing standalone diagnostic..." ` - -ForegroundColor Yellow -BackgroundColor Black + Write-Verbose -Message "Standalone server detected. Executing standalone diagnostic..." #-----------------Get VM Data Now--------------------- Write-Verbose -Message "Getting VM Information..." $quickCheck = Get-VM | Where-Object { $_.ReplicationState -ne "Disabled" } | Measure-Object | Select-Object -ExpandProperty count @@ -768,15 +778,16 @@ function Get-VMReplicationStatus { } <# .Synopsis - A VM is comprised of multiple components. Each can reside in a different location. This script will identify the location of all of those components + A VM has several components which can reside in a different location. This script will identify the location of all of VM components. .DESCRIPTION - A VM is comprised of a few components besides just .vhd/.vhdx. This will retrieve the location paths for the VM's configuration files, Snapshot Files, and Smart Paging files. If on a standalone it will display this information for all VMs on the standalone hyp. If a cluster is detected it will display this information for all VMs found on each node. + A VM is comprised of a few components besides just .vhd/.vhdx. This will retrieve the location paths for the VM's configuration files, + Snapshot Files, and Smart Paging files. If on a standalone it will display this information for all VMs on the standalone hyp. + If a cluster is detected it will display this information for all VMs found on each node. .EXAMPLE Get-VMLocationPathInfo This command will display the file paths for all VM components. .OUTPUTS - Cluster detected. Executing cluster appropriate diagnostic... ---------------------------------------------- HypV1 No VMs are present on this node. @@ -795,17 +806,18 @@ function Get-VMReplicationStatus { .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - it will automatically detect standalone or cluster and will run the appropriate diagnostic + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY - Get the following VM information for all detected Hyp nodes: - VMName - ComputerName - State - ConfigurationLocation - SnapshotFileLocation - SmartPagingFilePath + Get the following VM information for all detected Hyp nodes: + VMName + ComputerName + State + ConfigurationLocation + SnapshotFileLocation + SmartPagingFilePath #> function Get-VMLocationPathInfo { [CmdletBinding()] @@ -848,12 +860,12 @@ function Get-VMLocationPathInfo { -ForegroundColor White -BackgroundColor Black } #--------------END Get VM Data --------------------- - } + }#nodeConnectionTest else { Write-Verbose -Message "Connection unsuccesful." Write-Host "Node: $node could not be reached - skipping this node" ` -ForegroundColor Red - } + }#nodeConnectionTest } catch { Write-Host "An error was encountered with $node - skipping this node" ` @@ -898,7 +910,10 @@ function Get-VMLocationPathInfo { .Synopsis Displays IntegrationServicesVersion and enabled integration services for all VMs .DESCRIPTION - Gets the IntegrationServicesVersion and enabled integration services for all VMs. Automatically detects if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM integration services information for all VMs on the hyp. If a cluster is detected it will display VM integration services information for all VMs found on each node. + Gets the IntegrationServicesVersion and enabled integration services for all VMs. Automatically detects + if running on a standalone hyp or hyp cluster. If standalone is detected it will display VM integration + services information for all VMs on the hyp. If a cluster is detected it will display VM integration + services information for all VMs found on each node. .EXAMPLE Get-IntegrationServicesCheck @@ -927,9 +942,10 @@ function Get-VMLocationPathInfo { .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - it will automatically detect standalone or cluster and will run the appropriate diagnostic + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following VM information for all detected Hyp nodes: IntegrationServicesVersion @@ -1070,9 +1086,10 @@ function Get-IntegrationServicesCheck { .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info - it will automatically detect standalone or cluster and will run the appropriate diagnostic + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following VM information for all detected Hyp nodes: VMName @@ -1215,8 +1232,10 @@ function Get-BINSpaceInfo { .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following VM VHD information for all detected Hyp nodes: VhdType @@ -1427,28 +1446,16 @@ function Get-VMAllVHDs { Displays SupportPersistentReservations information for each VHD for every VM discovered. If SupportPersistentReservations is true, the VHD is shared .OUTPUTS - Standalone server detected. Executing standalone diagnostic... - ---------------------------------------------- - 2008R2Clust2 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 14 60 \\sofs-csv\VMs\2008R2Clust2\Virtual Hard Disks\2008R2Clust2.vhdx - ---------------------------------------------- - Web1 - - VhdType Size(GB) MaxSize(GB) Path - ------- -------- ----------- ---- - Dynamic 12 40 \\sofs-csv\VMs\Web1\Virtual Hard Disks\Web1.vhdx - ---------------------------------------------- - VMs are currently utilizing: 48 GB - VMs could POTENTIALLY Utilize: 180 GB - ---------------------------------------------- + VMName SupportPersistentReservations Path + ------ ----------------------------- ---- + TestVM-1 False C:\rs-pkgs\LocalVMs\VHDs\TestVM-1.vhdx .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following VM VHD information for all detected Hyp nodes: VMName @@ -1461,6 +1468,7 @@ function Get-SharedVHDs { Write-Host "Diag-V v$Script:version - Processing pre-checks. This may take a few seconds..." $adminEval = Test-RunningAsAdmin if ($adminEval -eq $true) { + $clusterEval = Test-IsACluster if ($clusterEval -eq $true) { #we are definitely dealing with a cluster - execute code for cluster Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..." @@ -1542,9 +1550,11 @@ function Get-SharedVHDs { .DESCRIPTION For single Hyper-V instances this function will pull available CPU and Memory physical resources. It will then tally all VM CPU and memory - allocations and contrast that info with available physical resources + allocations and contrast that info with available physical chassis resources A cpu ratio higher than 4:1 (vCPU:Logical Processors) will be flagged as bad + This ratio can be adjusted easily the the code below as there is no best practice + published around the most ideal CPU ratio. A static memory higher than 1:1 will be flagged as bad There is no best practice published around dynamic maximum memory so the function will only advise a warning if max memory is higher than available physical memory. @@ -1556,52 +1566,80 @@ function Get-SharedVHDs { Available storage space will also be calculated. For clusters CSV locations will be checked. For standalone Hyps any drive larger than 10GB and not C: will be checked. - In keeping with best practices anything with less than 20% free space will fail the - health check. + Drives under 1TB with less than 15% will be flagged as bad. Drives over 1TB with less + than 10% will be flagged as bad. .EXAMPLE Test-HyperVAllocation If executed on a standalone Hyper-V instance it will retrieve CPU/RAM physical resources If exectured on a Hyper-V cluster it will retrieve CPU/RAM physical resrouces for all nodes in the cluster and comapares those available resources to resources assigned - to VMs on each Hyper-V instance. + to VMs on each Hyper-V instance. Storage utilization will also be evaluated. .OUTPUTS - ----------------------------- + ---------------------------------------------------------------------- + SystemName: HYP1 + ---------------------------------------------------------------------- + Cores: 8 + Logical Processors: 16 + Total Memory: 32 GB + Avail Memory for VMs: 24 GB (8GB reserved for Hyper-V Host) + Current Free Memory: 6 GB + Total number of VMs: 1 + Total number of VM vCPUs: 8 + ---------------------------------------------------------------------- + Memory resources are still available: 19 % free + ---------------------------------------------------------------------- + Virtual Processors are not overprovisioned 1 : 1 + ---------------------------------------------------------------------- + Total Startup memory required for Dynamic VMs: 0 GB + Total Static memory required for Static VMs: 24 GB + ---------------------------------------------------------------------- + Total minimum RAM (Startup+Static) required: 24 GB + Minimum RAM: 24 GB is exactly at available RAM: 24 GB + ---------------------------------------------------------------------- + ---------------------------------------------------------------------- SystemName: HYP2 - ----------------------------- - Cores: 24 - Logical Processors: 48 - Total Memory: 256 GB - Free Memory: 248 GB - Number of VMs: 1 - Number of VM Procs: 2 - ----------------------------- + ---------------------------------------------------------------------- + Cores: 8 + Logical Processors: 16 + Total Memory: 32 GB + Avail Memory for VMs: 24 GB (8GB reserved for Hyper-V Host) + Current Free Memory: 31 GB + Total number of VMs: 0 + Total number of VM vCPUs: + ---------------------------------------------------------------------- Memory resources are still available: 97 % free - ----------------------------- + ---------------------------------------------------------------------- Virtual Processors are not overprovisioned 1 : 1 - ----------------------------- - Total Startup memory required for Dynamic VMs: 0 GB - Total Static memory required for Static VMs: 29 GB - ----------------------------- - Total minimum RAM (Startup+Static) required: 29 GB - Minimum RAM: 29 GB does not exceed available RAM: 256 GB - ----------------------------- + ---------------------------------------------------------------------- + Total Startup memory required for Dynamic VMs: 0 GB + Total Static memory required for Static VMs: 0 GB + ---------------------------------------------------------------------- + Total minimum RAM (Startup+Static) required: 0 GB + Minimum RAM: 0 GB does not exceed available RAM: 24 GB + ---------------------------------------------------------------------- + ---------------------------------------------------------------------- + N+1 Allocation Evaluation: + ---------------------------------------------------------------------- VMs would survive a one node failure - Total VM RAM minumum: 56 GB - Total Cluster RAM available with one node down: 256 GB - ----------------------------- + Total VM RAM minumum: 24 GB - Total Cluster RAM available with one node down: 24 GB + ---------------------------------------------------------------------- Storage Allocation Information - ----------------------------- - C:\ClusterStorage\Volume2 has the recommended 20% free space. - Free Space: 100 GB - Percent Free: 99.87756 - ----------------------------- + ---------------------------------------------------------------------- + C:\ClusterStorage\Volume1 has the recommended 15% free space. + Total Size: 500 GB + Free Space: 164 GB + Percent Free: 32.7383 + ---------------------------------------------------------------------- .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Function will automatically detect standalone or cluster and will run the appropriate diagnostic You can change the CPU ratio cutoff from 4:1 to say 6:1 or 8:1 by editing the Highlighted section below to suit your requirements + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following information for each Hyper-V instance found System Name @@ -1767,9 +1805,9 @@ function Test-HyperVAllocation { write-host "----------------------------------------------------------------------" -ForegroundColor Gray Write-Host "Cores:" $totalNumCores Write-Host "Logical Processors:" $totalNumLogicProcs - Write-Host "Total Memory:" $totalMemory GB - Write-Host "Free Memory:" $freeMemory GB "(8GB reserved for Hyper-V Host)" - Write-Host "Avail Memory for VMs: $availVMMemory GB" + Write-Host "Total Memory:" $totalMemory "GB" + Write-Host "Avail Memory for VMs: $availVMMemory GB (8GB reserved for Hyper-V Host)" + Write-Host "Current Free Memory:" $freeMemory "GB" Write-Host "Total number of VMs:" $vmCount Write-Host "Total number of VM vCPUs:" $totalVMProcCount write-host "----------------------------------------------------------------------" -ForegroundColor Gray @@ -2016,9 +2054,9 @@ function Test-HyperVAllocation { write-host "----------------------------------------------------------------------" -ForegroundColor Gray Write-Host "Cores:" $totalNumCores Write-Host "Logical Processors:" $totalNumLogicProcs - Write-Host "Total Memory:" $totalMemory GB - Write-Host "Free Memory:" $freeMemory GB "(8GB reserved for Hyper-V Host)" - Write-Host "Avail Memory for VMs: $availVMMemory GB" + Write-Host "Total Memory:" $totalMemory "GB" + Write-Host "Avail Memory for VMs: $availVMMemory GB (8GB reserved for Hyper-V Host)" + Write-Host "Current Free Memory:" $freeMemory "GB" Write-Host "Total number of VMs:" $vmCount Write-Host "Total number of VM vCPUs:" $totalVMProcCount write-host "----------------------------------------------------------------------" -ForegroundColor Gray @@ -2299,6 +2337,8 @@ function Get-CSVtoPhysicalDiskMapping { Diag-V .NOTES Author: Jake Morrison - TechThoughts - http://techthoughts.info + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get the following information for the specified path: Total size of all files found under the path @@ -2432,11 +2472,13 @@ function Get-FileSizes { Error 2 Critical 1 LogAlways 0 + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Retrieves Hyper-V Event Logs information #> function Get-HyperVLogs { - [cmdletbinding(DefaultParameterSetName = ’All’)] + [cmdletbinding(DefaultParameterSetName = 'All')] param ( [Parameter(Mandatory = $false, ParameterSetName = 'Time')] @@ -2532,16 +2574,14 @@ function Get-HyperVLogs { <# .Synopsis - Collection of several Hyper-V diagnostics that can be run via a simple choice menu + Console based GUI menu that gives quick access to a collection of several Hyper-V diagnostics .DESCRIPTION - Diag-V is a collection of various Hyper-V diagnostics. It presents the user - a simple choice menu that allows the user to select and execute the desired - diagnostic. Each diagnostic is a fully independent function which can be - copied and run independent of Diag-V if desired. + Presents all Diag-V diagnostics that can be run via a simple choice menu. + User can then select and execute the desired diagnostic. .EXAMPLE Show-DiagVMenu - + Displays a console menu that provides access to all Diag-V functions. .OUTPUTS Output will vary depending on the selected diagnostic. @@ -2566,8 +2606,9 @@ function Get-HyperVLogs { .COMPONENT Diag-V .NOTES - Author: Jake Morrison - TechThoughts - http://techthoughts.info + Author: Jake Morrison - TechThoughts - http://techthoughts.info + Contribute or report issues on this function: https://github.com/techthoughts2/Diag-V + How to use Diag-V: http://techthoughts.info/diag-v/ .FUNCTIONALITY Get-VMStatus ------------------------------ @@ -2590,6 +2631,8 @@ function Get-HyperVLogs { Get-CSVtoPhysicalDiskMapping ------------------------------ Get-FileSizes + ------------------------------ + Get-HyperVLogs #> function Show-DiagVMenu { #all this serves to do is to launch the parent menu choice option @@ -2836,18 +2879,19 @@ function showBasicDiags { if ($topLevel -eq 1) { Write-Host "Get-HyperVLogs function requires several parameters that you must specify. This text menu is not able to launch it." -ForegroundColor DarkCyan - Write-Host "Here are a few examples:" -ForegroundColor DarkCyan + Write-Host "Here are a few examples for you can reference when deciding how you want to run this function:" -ForegroundColor DarkCyan Write-Host "Get-HyperVLogs" -ForegroundColor Cyan Write-Host "Get-HyperVLogs -Newest 15 -Verbose" -ForegroundColor Cyan - Write-Host "Get-HyperVLogs -FilterText Switch -Newest 2 -ErrorsOnly -Verbose" -ForegroundColor Cyan - Write-Host "Get-HyperVLogs -StartDate 11/01/17 -ErrorsOnly" -ForegroundColor Cyan + Write-Host "Get-HyperVLogs -FilterText Switch -Newest 2 -WarningErrorCritical -Verbose" -ForegroundColor Cyan + Write-Host "Get-HyperVLogs -StartDate 11/01/17 -WarningErrorCritical" -ForegroundColor Cyan Write-Host "Get-HyperVLogs -StartDate 11/01/17 -EndDate 12/01/17" -ForegroundColor Cyan Write-Host "Get-HyperVLogs -LastMinutes 90 -Newest 20 -FilterText Switch" -ForegroundColor Cyan + Write-Host "Get-Help Get-HyperVLogs -Detailed" -ForegroundColor Magenta } elseif ($topLevel -eq 2) { Get-FileSizes } - elseif ($MenuChoice -eq 3) { + elseif ($topLevel -eq 3) { showTheTopLevel } else { diff --git a/README.md b/README.md index f943205..44bd1f5 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,66 @@ -# THIS BRANCH IS NOT PRODUCTION READY AT THIS TIME - # Diag-V Hyper-V Diagnostic Utility -### Synopsis -Collection of several Hyper-V diagnostics that can be run via a simple choice menu. +## Synopsis +PowerShell module containing several Hyper-V related diagnostics to assist with managing standalone Hyper-V Servers and Hyper-V clusters -### Description +## Description Diag-V is a PowerShell Module collection of primarily Hyper-V diagnostic functions, as well as several windows diagnostic functions useful when interacting with Hyper-V servers. With the module imported diagnostics can be run via the desired function name, alternatively, Diag-V can also present a simple choice menu that enables you to browse via console all diagnostics and execute the desired choice. -### Prerequisites +## Prerequisites * Designed and tested on Server 2012R2 and Server 2016 Hyper-V servers running PowerShell 5.1 * Most functions should work with PowerShell 4 * Diag-V must be run as a user that has local administrator rights on the Hyper-V server * If running diagnostics that interact with all cluster nodes Diag-V must be run as a user that has local administrator right to all members of the cluster -### How to run -1. -2. -3. Type in number to select desired diagnostic and execute +## How to run +### Install from PowerShell Gallery +1. TBD +### Manual Install from GIT +1. Download Zip file and extract +Module can be installed manualy by downloading Zip file and extract in two places: +2. Install module + * For all users: **%ProgramFiles%\WindowsPowerShell\Modules** (Recommended) + * For just you: **%UserProfile%\Documents\WindowsPowerShell\Modules** +3. Open Administrator ISE or PowerShell console session +3. Import module + * **Import-Module Diag-V** +4. Run desired diagnostic + * Directly by calling function name (see *Diagnsotic Functions* section below) + * Run GUI selection menu: + * **Show-DiagVMenu** - select desired diagnostic + +## Diagnostic Functions + +### VMs +* **Get-VMStatus** - Displays status for all VMs on a standalone Hyper-V server or Hyper-V cluster +* **Get-VMInfo** - Retrieves basic and advanced VM information for all VMs found on a standalone or cluster +* **Get-VMReplicationStatus** - Gets VM replication configuration and replication status for all detected VMs +* **Get-VMLocationPathInfo** - Identify the location of all of VM components. +* **Get-IntegrationServicesCheck** - Displays IntegrationServicesVersion and enabled integration services for all VMs +* **Get-BINSpaceInfo** - Determine if hard drive space is being taken up by the AutomaticStopAction setting +### VHDs +* **Get-VMAllVHDs** - VHD(x) information displayed for all discovered VMs +* **Get-SharedVHDs** - Evaluates if a VHDX is shared for all discovered VMs +### Overallocation +* **Test-HyperVAllocation** - Determines the current resource allocation health of Hyper-V Server or Hyper-V Cluster +### CSVs +* **Get-CSVtoPhysicalDiskMapping** - Resolves CSV to a physicalDisk drive +### Basic Diagnostics +* **Get-FileSizes** - Scans specified path and gets total size as well as top 10 largest files +* **Get-HyperVLogs** - Parses Hyper-V event logs and retrieves log entries based on user provided options -### Updates -* **?? December 2017** - * TBD +## Updates +* **12 December 2017** + * *Complete re-write* + * Converted Diag-V from a ps1 PowerShell script to a fully supported PowerShell module + * Redesigned all diagnostic functions + * Improved error control + * General bug fixes + * Better readability + * Added new Hyper-V log parser function * **04 Dec 2015** * Improved Cluster detection error control * Re-ordered the code of the diagnostics @@ -33,10 +69,10 @@ With the module imported diagnostics can be run via the desired function name, a * Fixed error where RAM was not being tallied properly * Added code to allow diagnostics to run correctly on VMM platforms -### Author +## Author Jake Morrison - Tech Thoughts - http://techthoughts.info -### Contributors +## Contributors * Marco-Antonio Cervantez * Dillon Childers -### Notes +## Notes From 01e14664f7f2cd5810ed5055833bdc8ad1bf835d Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Dec 2017 00:17:57 -0600 Subject: [PATCH 09/15] Minor README update for #1 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 44bd1f5..e945e69 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ With the module imported diagnostics can be run via the desired function name, a 1. Download Zip file and extract Module can be installed manualy by downloading Zip file and extract in two places: 2. Install module - * For all users: **%ProgramFiles%\WindowsPowerShell\Modules** (Recommended) - * For just you: **%UserProfile%\Documents\WindowsPowerShell\Modules** + * For all users: **%ProgramFiles%\WindowsPowerShell\Modules\Diag-V** (Recommended) + * For just you: **%UserProfile%\Documents\WindowsPowerShell\Modules\Diag-V** 3. Open Administrator ISE or PowerShell console session 3. Import module * **Import-Module Diag-V** From afd025594487497f0b264a5424c7a58ec4c0d4ce Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Dec 2017 00:37:34 -0600 Subject: [PATCH 10/15] Minor bug fix for #1 to account for down node with allocation diagnostic --- Diag-V.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Diag-V.psm1 b/Diag-V.psm1 index 833d4be..a8e0c6e 100644 --- a/Diag-V.psm1 +++ b/Diag-V.psm1 @@ -1670,7 +1670,7 @@ function Test-HyperVAllocation { #lets evaluate good communication to all nodes now Write-Verbose -Message "Performing connection test to node $node ..." try { - if (Test-Connection -ComputerName $node -ErrorAction Stop) { + if (Test-Connection -ComputerName $node -Quiet -ErrorAction Stop) { Write-Verbose -Message "Connection succesful." }#nodeConnectionTest else { From 817494c868dd4069fac51766b6476e6ba89c4d81 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Dec 2017 12:03:08 -0600 Subject: [PATCH 11/15] Cleaned up manifest for #1 --- Diag-V.psd1 | 60 +++-------------------------------------------------- 1 file changed, 3 insertions(+), 57 deletions(-) diff --git a/Diag-V.psd1 b/Diag-V.psd1 index dca6718..94c9e8a 100644 --- a/Diag-V.psd1 +++ b/Diag-V.psd1 @@ -32,39 +32,6 @@ # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '4.0' - # Name of the Windows PowerShell host required by this module - # PowerShellHostName = '' - - # Minimum version of the Windows PowerShell host required by this module - # PowerShellHostVersion = '' - - # Minimum version of the .NET Framework required by this module - # DotNetFrameworkVersion = '' - - # Minimum version of the common language runtime (CLR) required by this module - # CLRVersion = '' - - # Processor architecture (None, X86, Amd64) required by this module - # ProcessorArchitecture = '' - - # Modules that must be imported into the global environment prior to importing this module - # RequiredModules = @() - - # Assemblies that must be loaded prior to importing this module - # RequiredAssemblies = @() - - # Script files (.ps1) that are run in the caller's environment prior to importing this module - # ScriptsToProcess = @() - - # Type files (.ps1xml) to be loaded when importing this module - # TypesToProcess = @() - - # Format files (.ps1xml) to be loaded when importing this module - # FormatsToProcess = @() - - # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess - # NestedModules = @() - # Functions to export from this module FunctionsToExport = @( 'Get-VMStatus', @@ -82,28 +49,7 @@ 'Show-DiagVMenu' ) - # Cmdlets to export from this module - #CmdletsToExport = '*' - - # Variables to export from this module - #VariablesToExport = '*' - - # Aliases to export from this module - #AliasesToExport = '*' - - # List of all modules packaged with this module - # ModuleList = @() - - # List of all files packaged with this module - # FileList = @() - - # Private data to pass to the module specified in RootModule/ModuleToProcess - # PrivateData = '' - - # HelpInfo URI of this module - # HelpInfoURI = '' - - # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. - # DefaultCommandPrefix = '' - + #Specifies the URL of a web page about this project. + #ProjectUri = 'https://github.com/techthoughts2/Diag-V' + } \ No newline at end of file From e6125343a25f4ac5cff10d89f6be7c8ccbf9023f Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Dec 2017 13:40:59 -0600 Subject: [PATCH 12/15] Added additional manifest information for #1 --- Diag-V.psd1 | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/Diag-V.psd1 b/Diag-V.psd1 index 94c9e8a..37d5cae 100644 --- a/Diag-V.psd1 +++ b/Diag-V.psd1 @@ -9,25 +9,25 @@ @{ # Script module or binary module file associated with this manifest - RootModule = 'Diag-V.psm1' + RootModule = 'Diag-V.psm1' # Version number of this module. - ModuleVersion = '1.0' + ModuleVersion = '1.0' # ID used to uniquely identify this module - GUID = 'd0a9150d-b6a4-4b17-a325-e3a24fed0aa9' + GUID = 'd0a9150d-b6a4-4b17-a325-e3a24fed0aa9' # Author of this module - Author = 'Jake Morrison' + Author = 'Jake Morrison' # Company or vendor of this module - CompanyName = 'Tech Thoughts' + CompanyName = 'Tech Thoughts' # Copyright statement for this module - Copyright = '(c) 2017-2018 Jacob Morrison. All rights reserved.' + Copyright = '(c) 2017-2018 Jacob Morrison. All rights reserved.' # Description of the functionality provided by this module - Description = 'A Hyper-V Diagnostic Utility' + Description = 'A Hyper-V Diagnostic Utility' # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '4.0' @@ -49,7 +49,30 @@ 'Show-DiagVMenu' ) - #Specifies the URL of a web page about this project. - #ProjectUri = 'https://github.com/techthoughts2/Diag-V' + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = 'Hyper-V', 'Diag-V', 'Diagnostic', 'Tests', 'VM', 'VMs', 'VHDs', 'VHDXs', 'VHDX', + 'VHD', 'CSV', 'Overallocation', 'Overprovisioning', 'Virtual Machines', + 'Virtual Machine' + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/techthoughts2/Diag-V' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + + } # End of PrivateData hashtable - } \ No newline at end of file +} \ No newline at end of file From 442fafcbde5ac1dbf2cfa8800af4becf2ce73b32 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Dec 2017 13:46:36 -0600 Subject: [PATCH 13/15] Finalized README for #1 --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e945e69..ac9fc1a 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,15 @@ With the module imported diagnostics can be run via the desired function name, a * If running diagnostics that interact with all cluster nodes Diag-V must be run as a user that has local administrator right to all members of the cluster ## How to run -### Install from PowerShell Gallery -1. TBD +### Install from PowerShell Gallery (Recommended) +1. Open Administrator ISE or PowerShell console session +2. ```Install-Module -Name "Diag-V" -Repository PSGallery``` +3. Import module + * **Import-Module Diag-V** +4. Run desired diagnostic + * Directly by calling function name (see *Diagnsotic Functions* section below) + * Run GUI selection menu: + * **Show-DiagVMenu** - select desired diagnostic ### Manual Install from GIT 1. Download Zip file and extract Module can be installed manualy by downloading Zip file and extract in two places: @@ -76,3 +83,5 @@ Jake Morrison - Tech Thoughts - http://techthoughts.info * Dillon Childers ## Notes + +A complete write-up on Diag-V as well as a video demonstration can be found on the Tech Thoughts blog: http://techthoughts.info/diag-v/ \ No newline at end of file From 907684b83725ef606fd715c8c6e7ba4067dcfbc1 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Dec 2017 13:49:13 -0600 Subject: [PATCH 14/15] Finalized README for #1 --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ac9fc1a..03f51cf 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ With the module imported diagnostics can be run via the desired function name, a 1. Open Administrator ISE or PowerShell console session 2. ```Install-Module -Name "Diag-V" -Repository PSGallery``` 3. Import module - * **Import-Module Diag-V** + * ```Import-Module Diag-V``` 4. Run desired diagnostic * Directly by calling function name (see *Diagnsotic Functions* section below) * Run GUI selection menu: - * **Show-DiagVMenu** - select desired diagnostic + * ```Show-DiagVMenu``` - select desired diagnostic ### Manual Install from GIT 1. Download Zip file and extract Module can be installed manualy by downloading Zip file and extract in two places: @@ -33,11 +33,11 @@ Module can be installed manualy by downloading Zip file and extract in two place * For just you: **%UserProfile%\Documents\WindowsPowerShell\Modules\Diag-V** 3. Open Administrator ISE or PowerShell console session 3. Import module - * **Import-Module Diag-V** + * ```Import-Module Diag-V``` 4. Run desired diagnostic * Directly by calling function name (see *Diagnsotic Functions* section below) * Run GUI selection menu: - * **Show-DiagVMenu** - select desired diagnostic + * ```Show-DiagVMenu``` - select desired diagnostic ## Diagnostic Functions From 70b3149af24bba546e37e0e97b527205c36c4a88 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 10 Dec 2017 21:15:22 -0600 Subject: [PATCH 15/15] Minor updates to README for #1 --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 03f51cf..dd539f3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ With the module imported diagnostics can be run via the desired function name, a * ```Show-DiagVMenu``` - select desired diagnostic ### Manual Install from GIT 1. Download Zip file and extract -Module can be installed manualy by downloading Zip file and extract in two places: 2. Install module * For all users: **%ProgramFiles%\WindowsPowerShell\Modules\Diag-V** (Recommended) * For just you: **%UserProfile%\Documents\WindowsPowerShell\Modules\Diag-V** @@ -35,7 +34,7 @@ Module can be installed manualy by downloading Zip file and extract in two place 3. Import module * ```Import-Module Diag-V``` 4. Run desired diagnostic - * Directly by calling function name (see *Diagnsotic Functions* section below) + * Directly by calling function name (see *Diagnostic Functions* section below) * Run GUI selection menu: * ```Show-DiagVMenu``` - select desired diagnostic