Nagios for Hyper-V: Alert on Low Cluster Shared Volume Space

This article’s script could be run on any Windows cluster that uses Cluster Shared Volumes. It is simple: it looks for the CSV that you specified, finds out its total space, finds out its free space, calculates the percentage, and returns an OK, warning, or critical status. In order to use this script, you must have a functioning Nagios environment and the NSClient++ software installed on each node in the cluster(s) to be monitored. You must also have placed the clusterbase.ps1 script as indicated in the cluster base script article. None of the Hyper-V scripts are required for this check script to operate.

If you’re new to Nagios you should definitely check out the article How To: Monitor Hyper-V with Nagios first, then move onto the cluster base script article linked about, and continue reading below.

Note: In the update to 1.2, the script has been altered to alert at the level of USED space as opposed to the level of FREE space. That brings its behavior more inline with similar checks by other authors. Upon updating to version 1.2, modify your checks accordingly. For example, you might be using “check-csvspace!CSV1!20!10” to warn at 20% remaining and report critical at 10% remaining; that same check will now be “check-csvspace!CSV1!80!90”.

NSClient++ Configuration

These changes are to be made to the NSClient++ files on all Hyper-V hosts to be monitored.


C:Program FilesNSClient++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_csvspace=check_csvspace.ps1 $ARG1$ $ARG2$ $ARG3$

The NSClient++ service must be restarted after all changes to its ini file.


C:Program FilesNSClient++scriptscheck_csvspace.ps1

The required script clusterbase.ps1 must exist in the same folder.

<#
	check_csvspace.ps1
	Written by Eric Siron
	(c) Altaro Software 2017

	Version 1.2 November 19, 2017

	Intended for use with the NSClient++ module from http://nsclient.org
	Checks a Cluster Shared Volume's available space and returns the status to Nagios.
#>

param(
	[Parameter(Position = 1)][String]$CSVName,
	[Parameter(Position = 2)][UInt16]$WarningLevel,
	[Parameter(Position = 3)][UInt16]$CriticalLevel
)

if ([String]::IsNullOrEmpty($CSVName))
{
	Write-Host -Object 'No CSV was specified'
	Exit 3
}

$ClusterBase = Join-Path -Path $PSScriptRoot -ChildPath 'clusterbase.ps1'
. $ClusterBase

$CSVPartition = Get-ANClusterPartitionFromCSVName -CSVName $CSVName

if ($CSVPartition)
{
	if($WarningLevel -gt 100) { $WarningLevel = 100 }
	if($CriticalLevel -gt 100) { $CriticalLevel = 100 }
	$TotalSpace = $CSVPartition.TotalSize
	$FreeSpace = $CSVPartition.FreeSpace
	$FreePercent = $FreeSpace / $TotalSpace * 100
	$UsedSpace = $TotalSpace - $FreeSpace
	Write-Host -Object ('{0}MB free. {1}MB total. {2:N0}% free.|''CSV Used Space''={3}mb;{4};{5};;' -f $FreeSpace, $TotalSpace, $FreePercent, $UsedSpace, [uint32]($TotalSpace * $WarningLevel / 100), [uint32]($TotalSpace * $CriticalLevel / 100))
	if ($FreePercent -le (100 - $CriticalLevel))
	{
		exit 2
	}
	if ($FreePercent -le (100 - $WarningLevel))
	{
		exit 1
	}
}
else
{
	Write-Host -Object ('No CSV named {0} found.' -f $CSVName)
	exit 3
}
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. If you are not working with a Hyper-V system, then you can create any section heading that makes sense to you, or just insert the command wherever you like.

define command{
	command_name	check-csvspace
	command_line	$USER1$/check_nrpe -H $HOSTADDRESS$ -t 30 -p 5666 -c check_csvspace -a $ARG1$ $ARG2$ $ARG3$ $ARG4$ $ARG5$ $ARG6$
}

/usr/local/nagios/etc/objects/hypervhost.cfg

This file and section were created in the Hyper-V base scripts article. As long as it appears somewhere in one of the activated .cfg files, it will work.

This is a sample! You must use your own cluster name object!

###############################################################################
###############################################################################
#
# CLUSTER SERVICE DEFINITIONS
#
###############################################################################
###############################################################################

# check CLHV1 for CSV free space
define service{
	use			generic-service
	host_name		clhv1
	service_description	CSV1 Free Space
	check_command		check-csvspace!CSV1!80!90

Nagios must be restarted after these files are modified.

sudo service nagios checkconfig
sudo service nagios restart

 

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!

11 thoughts on "Nagios for Hyper-V: Alert on Low Cluster Shared Volume Space"

  • You can adapt your script to test all CSVs at once :

    File : check-all-csv-space.ps1

    Import-Module FailoverClusters

    param(
    [Parameter(Position=1)][UInt16]$WarningLevel,
    [Parameter(Position=2)][UInt16]$CriticalLevel
    )

    if([String]::IsNullOrEmpty($WarningLevel))
    {
    $WarningLevel = 10
    }

    if([String]::IsNullOrEmpty($CriticalLevel))
    {
    $CriticalLevel = 5
    }

    $NagiosStatus = 0
    $count = 0
    $objs = @()

    $allCSVs = Get-Cluster | Get-ClusterSharedVolume
    foreach ( $csv in $allCSVs )
    {
    ($csv | select-object -Property Name -ExpandProperty SharedVolumeInfo).Partition | ForEach-Object {
    $obj = New-Object PSObject -Property @{
    Name = $csv.Name
    Size = [int] ($_.Size /1GB)
    FreeSpace = [int] ($_.FreeSpace /1GB)
    UsedSpace = [int] ($_.UsedSpace /1GB)
    PercentFree = [int] $_.PercentFree
    }
    $objs = $objs $obj
    }
    }

    foreach ($lun in $objs){
    if($lun.Percentfree -lt $CriticalLevel){
    if ( $NagiosStatus -ne “2” ){ $NagiosStatus = “2” }
    write-host “CRITICAL : “$lun.name” Free :”$lun.PercentFree”% -” $lun.FreeSpace”GB / “$lun.size”GB”
    } elseif ( $lun.Percentfree -lt $WarningLevel ){
    if ( $NagiosStatus -eq “0” ){ $NagiosStatus = “1” }
    $count
    write-host “WARNING : “$lun.name” Free : “$lun.PercentFree”% -” $lun.FreeSpace”GB / “$lun.size”GB”
    }
    }
    # if more than $seuil Warnings => Critical
    $seuil = $objs.count * 3/4
    if ( $count -gt $seuil ){
    $NagiosStatus = “2”
    write-host “CRITICAL : ” $count “LUNs en WARNING”
    }

    exit $NagiosStatus

    having the call : check_command check-all-csv-space!10!5

    OK if all CSVs have free space > 10%
    Warning if one to “less than 3/4 of all” CSVs have space left 5%
    Critical if at least one CSV have less than 5% or “more than 3/4 of all” have space left <10%

    • Eric Siron says:

      Um, thanks? I guess…
      I wouldn’t ever want a glomming sensor when I can have individual sensors.
      You have a Write-Host inside a loop. Nagios guidelines recommend against that, and it makes the output look not so nice.
      It’s not bad, but not something that I would ever use.

  • Viktor Andersson says:

    Hey Eric!

    Trying to get this to work but all i get back is No CSV named XXX found. The name for the CSVs im using is the one found under failover cluster manager , storage and disks, same as you get when running Get-ClusterSharedVolume

    Any pointers(running this against a 2 node windows server 2016 hyper-v cluster)?

    • Eric Siron says:

      There are three cmdlets that retrieve the CSV by name.
      Run from a node:
      $CSVName = ‘whatever name’
      $CSVDiskPartition = Get-CimInstance -Namespace rootMSCluster -Class MSCluster_DiskPartition -Filter (‘FileSystem=”CSVFS” AND VolumeLabel=”{0}”‘ -f $CSVName)
      Get-CimInstance -Namespace rootMSCluster -Class MSCluster_ClusterSharedVolume -Filter (‘VolumeName=”{0}”‘ -f ($CSVDiskPartition.Path -replace ‘\’, ‘\’))

      If the end doesn’t produce anything, make sure that $CSVDiskPartition holds data.
      If all this works, then I would suspect some permission problem.

      • Viktor Andersson says:

        Thanks for taking the time to respond Eric!

        I’ve tried to run Get-CimInstance -Namespace rootMSCluster -Class MSCluster_DiskPartition -Filter ‘FileSystem=”CSVFS” AND VolumeLabel=”{0}”‘ on a node but i get the response:

        Get-CimInstance : Invalid query
        At line:1 char:1
        Get-CimInstance -Namespace rootMSCluster -Class MSCluster_DiskPartit …
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        CategoryInfo : InvalidArgument: (:) [Get-CimInstance], CimException
        FullyQualifiedErrorId : HRESULT 0x80041017,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand

        If i remove the volumelabel part of it it returns data and i can see the two CSV volumes:
        Get-CimInstance -Namespace rootMSCluster -Class MSCluster_DiskPartition -Filter ‘FileSystem=”CSVFS”‘

        • Eric Siron says:

          The {0} in quotes is a formatter. Either you have to enter that part in parentheses with the -f the way that I have it or you have to explicitly replace the {0} with your CSV’s name.

          • Viktor Andersson says:

            Problem seems to be that the VolumeLabel is empty on both of my CSV’s, that field contains nothing.

            I dont dare to update the label if its even possible through some powershell script, this is production and has many VMs on it. I made a change to the clusterbase powershell script instead so it filters on VolumeGuid, maybe not optimal but that works.

            Thanks for your time!

          • Eric Siron says:

            I have an extremely busy schedule but at some point I might consider addressing this. If I get some bandwidth, I will look at the effects of renaming a CSV on the fly. I’ve never tried to do that, and I like a challenge.

  • Brian says:

    Im getting the following output, maybe you can assist. Whatever the CSV is, we’re not getting the correct data.

    PS C:Program FilesNSClient scripts> .check_csv_freespace.ps1

    cmdlet check_csv_freespace.ps1 at command pipeline position 1
    Supply values for the following parameters:
    csvname: CSV01
    warnlevel: 80
    critlevel: 90
    Attempted to divide by zero.
    At C:Program FilesNSClient scriptscheck_csv_freespace.ps1:36 char:1
    $usedpercent = [math]::truncate(($usedspace / $capacity) * 100)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CategoryInfo : NotSpecified: (:) [], RuntimeException
    FullyQualifiedErrorId : RuntimeException

    Attempted to divide by zero.
    At C:Program FilesNSClient scriptscheck_csv_freespace.ps1:37 char:1
    $freepercent = [math]::truncate(($freespace / $capacity) * 100)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CategoryInfo : NotSpecified: (:) [], RuntimeException
    FullyQualifiedErrorId : RuntimeException

    OK – CSV01 total: GB, used: 0GB (%), free: GB (%) | ‘CSV01 used_space’=0Gb;0;0;0;

  • Brian says:

    When I run this from the node itself I get the following.

    PS C:Program FilesNSClient scripts> .check_csvspace.ps1
    No CSV was specified

Leave a comment or ask a question

Your email address will not be published. Required fields are marked *

Your email address will not be published.

Notify me of follow-up replies via email

Yes, I would like to receive new blog posts by email

What is the color of grass?

Please note: If you’re not already a member on the Dojo Forums you will create a new account and receive an activation email.