The script in this article will examine a specific VHD or VHDX on a specific virtual machine. If it is dynamically expanding, it will report the maximum size, the currently allocated size, the potential amount of expansion, and the current expansion percentage. If the currently expanded size exceeds thresholds that you set, it will trigger a Warning or Critical condition. To use this script, you must have a functional Nagios and NSClient++ installation as detailed in our main Nagios article. You must also have the required base scripts on your Hyper-V hosts.
Update History
- November 5, 2016: 1.2.0. Output includes performance data.
- May 23rd, 2017: Updated to version 1.1.0. Improved error controls and accuracy; should reduce false errors. Now dependent on v1.1.1 of hvdiskbase.ps1.
- May 21st, 2017
- Updated hvdiskbase.ps1 to version 1.1. The script on this page remains unchanged, but its behavior will change due to the underlying hvdiskbase.ps1 change. Reports will now be accurate for disks attached to offline virtual machines.
- May 5th, 2017: Updated to version 1.0.1
NSClient++ Configuration
These changes are to be made to the NSClient++ files on all Hyper-V hosts with virtual machines that are to be monitored.
C:\Program Files\NSClient++\nsclient.ini
If the indicated INI section does not exist, create it. Otherwise, just add the second line to the existing section.
[/settings/external scripts/wrapped scripts] check_vmdyndisksize=check_hvvmdyndisksize.ps1 $ARG1$ $ARG2$ $ARG3$ $ARG4$ $ARG5$ $ARG6$
C:\Program Files\NSClient++\scripts\check_hvvmdyndisksize.ps1
This script examines a Hyper-V dynamically expanding virtual disk and reports to Nagios on its space utilization. This file does not exist and must be created.
<# check_hvvmdyndisksize.ps1 Written by Eric Siron (c) Altaro Software 2016 Version 1.2.0 November 5, 2017 Intended for use with the NSClient++ module from http://nsclient.org Checks how far a dynamic disk has expanded toward its maximum size and returns the result to Nagios. #> param( [Parameter(Mandatory=$true, Position=1)][String]$VMName, [Parameter(Mandatory=$true, Position=2)][String]$ControllerType, [Parameter(Mandatory=$true, Position=3)][UInt32]$ControllerNumber, [Parameter(Mandatory=$true, Position=4)][UInt32]$ControllerLocation, [Parameter(Position=5)][UInt32]$WarningPercent = 75, [Parameter(Position=6)][UInt32]$CriticalPercent = 90 ) $VMBase = Join-Path -Path $PSScriptRoot -ChildPath 'hvvmbase.ps1' . $VMBase if(-not (Test-Path -Path $VMBase)) { Write-Host ('Required file {0} not found' -f $VMBase) exit 3 } $DiskBase = Join-Path -Path $PSScriptRoot -ChildPath 'hvdiskbase.ps1' . $DiskBase if(-not (Test-Path -Path $DiskBase)) { Write-Host ('Required file {0} not found' -f $VMBase) exit 3 } $CurrentDiskScriptVer = Get-ANDiskBaseVersion $RequiredDiskcriptVer = New-Object System.Version(1, 1, 1, 0) if($CurrentDiskScriptVer -lt $RequiredVMScriptVer) { Write-Host ('Required disk base script version: {0}. Current version: {1}' -f $RequiredDiskcriptVer, $CurrentDiskScriptVer) Exit 3 } $Disk = Get-ANVMDisk -VMName $VMName -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation $DiskSettingData = Get-ANVHDSettingData -Disk $Disk if($DiskSettingData.Type -eq 3 -bor $DiskSettingData.Type -eq 4) { $DiskState = Get-ANVHDState -Disk $Disk $AllocatedSpace = $DiskState.FileSize $RawPercentage = $AllocatedSpace / $DiskSettingData.MaxInternalSize $UnallocatedSpace = $DiskSettingData.MaxInternalSize - $AllocatedSpace Write-Host ('Name: {0}. Max size: {1}. Allocated space: {2} ({3}). Expandable space: {4}.|''CSV Expansion''={5}b;{6};{7};;' -f ` ($Disk.HostResource[0] -replace '(.*\\)(.*)', '$2'), (Format-ANStorageNumberAsFriendly -Number $DiskSettingData.MaxInternalSize), (Format-ANStorageNumberAsFriendly -Number $AllocatedSpace), (Format-ANNumberAsPercent -Number $RawPercentage), (Format-ANStorageNumberAsFriendly -Number $UnallocatedSpace), $AllocatedSpace, [uint64]($DiskSettingData.MaxInternalSize * $WarningPercent / 100), [uint64]($DiskSettingData.MaxInternalSize * $CriticalPercent / 100) ) if(($RawPercentage * 100) -ge $CriticalPercent) { Exit 2 } if(($RawPercentage * 100) -ge $WarningPercent) { Exit 1 } } else { Write-Host ('{0} is fixed size.' -f $Disk.HostResource[0]) } Exit 0
Nagios Configuration
These changes are to be made on the Nagios host. I recommend using WinSCP as outlined in our main Nagios and Ubuntu Server articles.
/usr/local/nagios/etc/objects/commands.cfg
The Hyper-V Host Commands section should already exist if you followed our main Nagios article. Add this command there.
################################################################################ # # Hyper-V Host Commands # ################################################################################ # $ARG1$: virtual machine name (as shown in Get-VM) # $ARG2$: s for SCSI, i for IDE # $ARG3$: controller number that contains the disk ex: 0 # $ARG4$: disk number on the controller # $ARG5$: percentage of expanded space that triggers a warning condition, ex: 75 # $ARG6$: percentage of expanded space that triggers a critical condition, ex: 90 define command{ command_name check-dynamicdisk-size command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -t 30 -p 5666 -c check_vmdyndisksize -a $ARG1$ $ARG2$ $ARG3$ $ARG4$ $ARG5$ $ARG6$ }
/usr/local/nagios/etc/objects/hypervhost.cfg
This file and section was created in the required base scripts article. The below shows multiple examples for creating services for the new command to check.
###################################################################### ############################################################################### # # HYPER-V SERVICE DEFINITIONS # ############################################################################### ############################################################################### # this is a highly-available VM; only check the cluster object # make sure the account NSClient++ is running under has administrative access to all nodes! define service{ use generic-service host_name clhv1 service_description VM svmanage: OS Disk Expansion check_command check-dynamicdisk-size!svmanage!i!0!0!75!90 } # this is a non-HA VM; only check the owning host define service{ use generic-service host_name svhv1 service_description VM svdc1: OS Disk Expansion check_command check-dynamicdisk-size!svdc1!s!0!0!75!90 } # this is a non-HA VM; only check the owning host define service{ use generic-service host_name svhv1 service_description VM svlmon1: OS Disk Expansion check_command check-dynamicdisk-size!svlmon1!i!0!0!75!90 } # this is a non-HA VM; only check the owning host define service{ use generic-service host_name svhv2 service_description VM svdc2: OS Disk Expansion check_command check-dynamicdisk-size!svdc2!s!0!0!75!90 }
These checks must be made by scanning the Hyper-V hosts, not the virtual machines themselves, so apply services to clusters or hosts accordingly. For highly-available VMs, always target the cluster object, not any particular node. Otherwise, the check will start throwing errors when the guest moves to another node. For a breakdown of what each individual argument means, look at the command definition in the listing immediately above this one.