Nagios for Hyper-V: Monitoring Dynamically Expanding VHDX Size

Table of contents

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.

Altaro Hyper-V Backup
Share this post

Not a DOJO Member yet?

Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!