Nagios for Hyper-V: Required Base Scripts

Table of contents

To use this article, you will need to have a functioning Nagios environment with the CHECK_NRPE plugin. Your Hyper-V hosts will need to have NSClient++ installed. Both will need to have the configuration as explained near the end of my Nagios configuration article.

Update History

  • May 24th, 2017
    • Updated hvdiskbase.ps1 to version 1.2. Corrects sporadic issues for cluster VMs introduced in 1.1. Depends on hvvmbase 1.0.2
    • Updated hvvmbase.ps1 to version 1.0.2. Adds resilience to cluster VM location
  • May 23rd, 2017
    • Updated hvdiskbase.ps1 to version 1.1.1. Minor changes to improve dependent script error controls.
  • May 21st, 2017
    • Updated hvdiskbase.ps1 to version 1.1. Breaking change: This updates the Get-ANVMDisk function so that it works with offline as well as online virtual machines. It does not affect the scripts published on this site.
  • May 17th, 2017
    • Updated hvvmbase.ps1 to version 1.0.1
    • Updated hvdiskbase.ps1 to version 1.0.1
    • Added anutilitybase.ps1

Nagios Configuration Files

This section shows changes and additions that must be made to the Nagios configuration files.

Modify the displayed portion of these files with the highlighted section. If nothing is highlighted, then just add it to the bottom.

Important notes:

  1. Do not forget to swap out my host and object names for your own!
  2. Do not forget to use ‘service nagios checkconfig’ before trying to apply ANY changes.

After the configuration changes are complete, use service nagios restart  on the Nagios system to apply them.

/usr/local/nagios/etc/nagios.cfg

Notice that you must uncomment the windows.cfg line.

# OBJECT CONFIGURATION FILE(S)
# These are the object configuration files in which you define hosts,
# host groups, contacts, contact groups, services, etc.
# You can split your object definitions across several config files
# if you wish (as shown below), or keep them all in a single config file.

# You can specify individual object config files as shown below:
cfg_file=/usr/local/nagios/etc/objects/commands.cfg
cfg_file=/usr/local/nagios/etc/objects/contacts.cfg
cfg_file=/usr/local/nagios/etc/objects/timeperiods.cfg
cfg_file=/usr/local/nagios/etc/objects/templates.cfg

# Definitions for monitoring Hyper-V Hosts
cfg_file=/usr/local/nagios/etc/objects/hypervhost.cfg

# Definitions for monitoring the local (Linux) host
cfg_file=/usr/local/nagios/etc/objects/localhost.cfg

# Definitions for monitoring a Windows machine
cfg_file=/usr/local/nagios/etc/objects/windows.cfg

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

The backing scripts for the commands listed below will appear in other articles. These are examples of how they will be entered. If you have a method that fits your environment more efficiently, use it.

################################################################################
#
# Hyper-V Host Commands
#
################################################################################

# $ARG1$: age that triggers a warning condition. use one letter (m = minute, h = hour, d = day, w = week) and one number. ex: 3d for 3 days. order does not matter
# $ARG2$ age that triggers a critical condition
define command{
	command_name	check-checkpoint-age
	command_line	$USER1$/check_nrpe -H $HOSTADDRESS$ -t 30 -p 5666 -c check_checkpointage -a $ARG1$ $ARG2$
}

# $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 an error 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 doesn’t exist — you’ll have to create it. If you do not have a Hyper-V cluster, ignore those sections.

###############################################################################
###############################################################################
#
# HYPER-V HOSTGROUP DEFINITION
#
###############################################################################
###############################################################################

define hostgroup{
	hostgroup_name		hyper-v-servers
	alias			Hyper-V Servers
	members			svhv1, svhv2
}

###############################################################################
###############################################################################
#
# HYPER-V HOST DEFINITIONS
#
###############################################################################
###############################################################################

define host{
	use			windows-server
	host_name		svhv1
	alias			Hyper-V Host 1
	address			192.168.25.10
}

define host{
	use			windows-server
	host_name		svhv2
	alias			Hyper-V Host 2
	address			192.168.25.11
}

###############################################################################
###############################################################################
#
# HYPER-V CLUSTER HOSTGROUP DEFINITION
#
###############################################################################
###############################################################################

define hostgroup{
	hostgroup_name		hyper-v-clusters
	alias			Hyper-V Clusters
	members			clhv1
}

###############################################################################
###############################################################################
#
# HYPER-V CLUSTER HOST OBJECT DEFINITION
#
###############################################################################
###############################################################################

define host{
	use			generic-hyper-v-cluster
	host_name		clhv1
	alias			Hyper-V Cluster 1
	address			192.168.25.20
}

###############################################################################
###############################################################################
#
# 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
}

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

This addition is only necessary if you will be monitoring a Hyper-V cluster.

#### Hyper-V Cluster Template ####
define host{
	name			generic-hyper-v-cluster
	use			generic-host
	check_period		24x7
	check_interval		5
	retry_interval		1
	max_check_attempts	10
	check_command		check-host-alive
	notification_period	24x7
	notification_interval	30
	notification_options	d,r
	hostgroups		hyper-v-clusters
	register		0
}

NSClient++ Configuration

The additions and changes in this section are made on Hyper-V hosts that are running NSClient++. No checks are included in this article. These scripts are required for scripts that I’ll present in other articles.

All scripts have been tested with PowerShell version 4.0. There is no known reason why they would not work with PowerShell 5.0 or later.


A Note on the PowerShell Scripts

When I share scripts with you, it is with the genuine hope that they’ll be useful. I certainly don’t mind if you pick them apart for learning, for improving, for bug hunting, or pretty much anything that doesn’t involve stealing my work to claim as your own. If you look at these scripts, you will see many, many, many places where I could have used a completely different cmdlet and saved myself lots of trouble and several lines of script. You’ll also notice that I used almost zero comments. I promise you that I did not intentionally make these scripts difficult to read. These scripts are going to be executed frequently on every host where they reside. I also have no idea what you have or have not done in your environment. Therefore, I rigidly adhered to two goals when designing these scripts:

  • Reduction of non-essential information. This mostly meant, “very few comments”. I don’t know how much it really saves, but I tend to write almost as many comment lines as script lines so it seemed possible that forcing the PowerShell interpreter to examine and ignore dozens of comment lines would become a drag in aggregate. I avoided positional parameters and aliases because I did not feel that the readability trade-off was worth the effort when I was also avoiding comments and also because I assume that PowerShell burns up CPU cycles figuring out positional parameters and aliases just like people do.
  • No assumptions of the presence of any PowerShell modules except what is in the base package. If any of my Nagios scripts call a cmdlet that doesn’t exist, either you didn’t copy everything that I told you to or your PowerShell installation is damaged. I did not use common Hyper-V or Failover Clustering cmdlets because I cannot be certain that Get-VM will work on a Hyper-V host or that Get-ClusterResource will work on a failover cluster member because their PowerShell modules are optional. Additionally, I assume that not requiring PowerShell to load up or hook into those DLLs or follow the deeper logic trails that Microsoft used in those cmdlets should speed up processing to some degree.

I did attempt to make the scripts as legible as possible while following those goals.

Remember that every host must have its execution policy set to RemoteSigned or something less restrictive. You can run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned.


C:\Program Files\NSClient++\nsclient.ini

The base Nagios article includes a section on configuring the ini file correctly. The portion that establishes PowerShell functionality and a couple of samples for checks are shown below:

[/settings/external scripts]
allow arguments = true

[/settings/external scripts/wrappings]
ps1=cmd /c echo scripts\%SCRIPT% %ARGS%; exit($lastexitcode) | powershell.exe -noprofile -nologo -command -

[/settings/external scripts/wrapped scripts]
check_checkpointage=check_hvcheckpointage.ps1 $ARG1$ $ARG2$
check_vmdyndisksize=check_hvvmdyndisksize.ps1 $ARG1$ $ARG2$ $ARG3$ $ARG4$ $ARG5$ $ARG6$

C:\Program Files\NSClient++\scripts\hvvmbase.ps1

This script contains some general-purpose and virtual machine-related functions that will be used by my other scripts that perform Hyper-V host checks. This file does not exist and must be created.

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

	Version 1.0.2 May 24, 2017

	Intended for use with the NSClient++ module from http://nsclient.org
	Provides reusable functions for other check scripts.
#>
if(-not $HVVMBaseIncluded)
{
	$HVVMBaseIncluded = $true

	$UtilityBase = Join-Path -Path $PSScriptRoot -ChildPath 'anutilitybase.ps1'
	if(-not (Test-Path -Path $UtilityBase))
	{
		Write-Host ('Required file {0} not found' -f $UtilityBase)
		exit 3
	}
	. $UtilityBase

	function Get-ANVMBaseVersion
	{
		New-Object System.Version(1, 0, 2, 0)
	}

	function Get-ANVMsAll
	{
		param(
			[Parameter()][String]$ComputerName = $env:COMPUTERNAME
		)
		Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -ComputerName $ComputerName
	}

	function Get-ANVMWmiObjectFromComputer
	{
		param(
			[Parameter(Position=1)][String]$ComputerName,
			[Parameter(ParameterSetName='By Name', Position=2)][String]$VMName,
			[Parameter(ParameterSetName='By ID')][String]$VMID
		)
		if($VMName)
		{
			$Filter = 'ElementName="{0}"' -f $VMName
		}
		elseif($VMID)
		{
			$Filter = 'Name="{0}"' -f $VMID
		}
		else
		{
			return
		}
		$GWMIParams = @{Namespace = 'root\virtualization\v2'; Class = 'Msvm_ComputerSystem'; Filter = $Filter; ErrorAction = ([System.Management.Automation.ActionPreference]::SilentlyContinue) }
		if($ComputerName -and $ComputerName -ne $env:COMPUTERNAME)
		{
			$GWMIParams.Add('ComputerName', $ComputerName)
		}
		Get-WmiObject @GWMIParams # -ComputerName $ComputerName -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' -Filter $Filter -ErrorAction SilentlyContinue
	}

	# will find ANY VM on the local host and any HA VM in the same cluster. will NOT find non-HA VMs on other nodes
	# if multiple VMs have the same name, will return whichever one that it wants to. I'm not sure how it decides. #sorrynotsorry
	function Get-ANVMWmiObject
	{
		param(
			[Parameter(Position=1)][String]$VMName
		)

		if(-not $VMName)
		{
			Write-Host 'No virtual machine name was supplied'
			Exit 2
		}

		# look locally first
		$VM = Get-ANVMWmiObjectFromComputer -ComputerName '.' -VMName $VMName
		if((-not $VM) -band (ANIsClustered))
		{
			$VMsOnOtherHosts = Get-WmiObject -Namespace root\MSCluster -Class MSCluster_Resource -Property OwnerNode, Id -Filter ('Type="Virtual Machine" AND NOT OwnerNode="{0}"' -f $env:COMPUTERNAME)
			$ClusterKey = $null

			try
			{
				$ClusterKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryView]::Default)
			}
			catch [System.Security.SecurityException], [System.UnauthorizedAccessException]
			{
				Write-Host ('NSClient++ user "{0}" cannot access the registry on "{1}"' -f $env:USERNAME, $OtherHostVM.OwnerNode, $env:COMPUTERNAME)
				Exit 2
			}
			catch
			{
				Write-Host ('Could not open registry on "{0}": {1}' -f $env:COMPUTERNAME, $_)
				Exit 2
			}

			foreach($OtherHostVM in $VMsOnOtherHosts)
			{
				try
				{
					$Subkey = $ClusterKey.OpenSubKey(('Cluster\Resources\{0}\Parameters' -f $OtherHostVM.Id), $false)
					$VMId = $Subkey.GetValue('VmID')
				}
				catch
				{
					Write-Host ('Could not open a cluster parameters key on "{0}": {1}' -f $env:COMPUTERNAME, $_)
					Exit 2
				}
				$Subkey.Close()
				$VM = Get-ANVMWmiObjectFromComputer -ComputerName $OtherHostVM.OwnerNode -VMID $VMId
				if($VM -ne $null -and $VM.ElementName -eq $VMName)
				{
					break
				}
				else
				{
					$VM = $null
				}
			}
		}
		if(-not $VM)
		{
			Write-Host ('Virtual machine "{0}" could not be found!' -f $VMName)
			Exit 2
		}
		$VM
	}

	function Get-ANVMIsClustered
	{
		param([Parameter(Position=1)][System.Management.ManagementObject]$VM)
		$IsClustered = $false
		$VMHostData = $VM.GetRelated('Msvm_VirtualSystemSettingData').GetRelated('Msvm_KvpExchangeComponentSettingData').HostOnlyItems
		foreach ($XMLKVPItem in $VMHostData)
		{
			$KVPKey = ([XML]$XMLKVPItem).SelectSingleNode('/INSTANCE/PROPERTY[@NAME=''Name'']/VALUE/child::text()').Value
			if($KVPKey -eq 'VirtualMachineIsClustered')
			{
				$KVPValue = ([XML]$XMLKVPItem).SelectSingleNode('/INSTANCE/PROPERTY[@NAME=''Data'']/VALUE/child::text()').Value
				$IsClustered = $KVPValue -eq 'TRUE'
			}
		}
		$IsClustered
	}
}

 

C:\Program Files\NSClient++\scripts\hvdiskbase.ps1

This script contains functions that will be used by my other scripts that work with Hyper-V virtual hard disks. This file does not exist and must be created.

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

	Version 1.2.0 May 24, 2017

	Intended for use with the NSClient++ module from http://nsclient.org
	Provides reusable functions for other check scripts.
#>

if(-not $HVDiskBaseIncluded)
{
	$HVDiskBaseIncluded = $true

	$UtilityBase = Join-Path -Path $PSScriptRoot -ChildPath 'anutilitybase.ps1'
	if(-not (Test-Path -Path $UtilityBase))
	{
		Write-Host ('Required file {0} not found' -f $UtilityBase)
		exit 3
	}
	. $UtilityBase

	$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
	}

	$CurrentVMScriptVer = Get-ANVMBaseVersion
	$RequiredVMScriptVer = New-Object System.Version(1, 0, 2, 0)
	if($CurrentVMScriptVer -lt $RequiredVMScriptVer)
	{
		Write-Host ('Required VM base script version: {0}. Current version: {1}' -f $RequiredVMScriptVer, $CurrentVMScriptVer)
		exit(3)
	}

	function Get-ANDiskBaseVersion
	{
		New-Object System.Version(1, 2, 0, 0)
	}

	function Get-ANImageManagementService
	{
		param([Parameter(Position=1)][String]$ComputerName)
		if([String]::IsNullOrEmpty($ComputerName))
		{
			$ComputerName = '.'
		}
		Get-WmiObject -ComputerName $ComputerName -Namespace root\virtualization\v2 -Class Msvm_ImageManagementService
	}

	function Get-ANVMDisk
	{
		param(
			[Parameter(Position=1)][String]$VMName = '',
			[Parameter(Position=2)][String]$ControllerType = 'i',
			[Parameter(Position=3)][UInt32]$ControllerNumber = '0',
			[Parameter(Position=4)][UInt32]$ControllerLocation = '0'
		)

		$VM = Get-ANVMWmiObject -VMName $VMName
		if($VM)
		{
			if($ControllerType.Contains('s'))
			{
				$SearchType = 6
			}
			else
			{
				$SearchType = 5
			}
			$ComputerName = [String]::Empty
			if($VM.__SERVER -ne $env:COMPUTERNAME)
			{
				$ComputerName = $VM.__SERVER
			}
			$GwmiParams = @{Namespace = 'root\virtualization\v2'; Class = 'Msvm_ResourceAllocationSettingData'; Filter = ('InstanceID LIKE "%{0}%" AND ResourceType="{1}"' -f $VM.Name, $SearchType)}
			if($ComputerName) { $GwmiParams.Add('ComputerName', $ComputerName)}

			$VMRASD = Get-WmiObject @GwmiParams
			if($VMRASD -and $VMRASD.Count)
			{
				$VMRASD = $VMRASD[$ControllerNumber]
			}
			if($VMRASD)
			{
				$SearchPath = $VMRASD.Path.Path
				$SearchPath = $SearchPath.Substring(0, $SearchPath.Length - 1)
				$SearchPath += '\\{0}\\D"' -f $ControllerLocation
				$SearchPath = $SearchPath.Replace('\', '\\')
				$GwmiParams.Class = 'Msvm_StorageAllocationSettingData'
				$GwmiParams.Filter = ("Parent='{0}'" -f $SearchPath)
				$VMSASD = Get-WmiObject @GwmiParams
				if($VMSASD)
				{
					$VMSASD
				}
				else
				{
					'No disk found at the specified controller location'
					exit 3
				}
			}
			else
			{
				'Specified controller was not found'
				exit 3
			}
		}
		else
		{
			Write-Host ('Virtual machine "{0}" not found' -f $VMName)
			exit 3
		}
	}

	function Get-ANVHDSettingData
	{
		param(
			[Parameter(Position=1)][System.Management.ManagementObject]$Disk
		)
		if($Disk -and $Disk.HostResource[0].ToLower().Contains('.vhd'))
		{
			$ImageManagementService = Get-ANImageManagementService -ComputerName $Disk.__SERVER
			$SettingData = $ImageManagementService.GetVirtualHardDiskSettingData($Disk.HostResource[0])
			if($SettingData.ReturnValue -eq 0)
			{
				try
				{
					$XMLData = [xml]$SettingData.SettingData
					if($XMLData.SelectSingleNode('/INSTANCE/@CLASSNAME').Value -ne 'Msvm_VirtualHardDiskSettingData')
					{
						throw('Data is not of type Msvm_VirtualHardDiskSettingData')
					}
				}
				catch
				{
					Write-Host ('Error parsing setting data for {0}: {1}' -f $Disk.HostResource[0], $_)
					Exit 2
				}
				$RawBlockSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''BlockSize'']/VALUE/child::text()').Value
				$RawFormat = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Format'']/VALUE/child::text()').Value
				$RawType = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Type'']/VALUE/child::text()').Value
				$RawParentPath = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''ParentPath'']/VALUE/child::text()').Value
				$RawPath = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Path'']/VALUE/child::text()').Value
				$RawLogicalSectorSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''LogicalSectorSize'']/VALUE/child::text()').Value
				$RawMaxInternalSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''MaxInternalSize'']/VALUE/child::text()').Value
				$RawPhysicalSectorSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''PhysicalSectorSize'']/VALUE/child::text()').Value
				$RawVirtualDiskId = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''VirtualDiskId'']/VALUE/child::text()').Value

				try
				{
					$WMISettingData = ([wmiclass]('\\{0}\root\virtualization\v2:Msvm_VirtualHardDiskSettingData' -f $Disk.__SERVER)).CreateInstance()
				}
				catch
				{
					Write-Host ('Unable to create a disk setting data object: {0}' -f $_)
					Exit 2
				}
				$WmiSettingData.BlockSize = $RawBlockSize
				$WmiSettingData.Format = $RawFormat  # Fixed = 2, Dynamic = 3, Differencing = 4
				$WmiSettingData.Type = $RawType # VHD = 2, VHDX = 3
				$WMISettingData.ParentPath = $RawParentPath
				$WmiSettingData.Path = $RawPath
				$WMISettingData.LogicalSectorSize = $RawLogicalSectorSize
				$WmiSettingData.MaxInternalSize = $RawMaxInternalSize
				$WmiSettingData.PhysicalSectorSize = $RawPhysicalSectorSize
				$WmiSettingData.VirtualDiskId = $RawVirtualDiskId
				$WmiSettingData
			}
			else
			{
				Write-Host ('Unable to retrieve setting data for {0}' -f $Disk.HostResource[0])
				Exit 2
			}
		}
		else
		{
			Write-Host 'Disk not found or is not a virtual hard disk'
			Exit 3
		}
	}

	function Get-ANVHDState
	{
		param(
			[Parameter(Position=1)][System.Management.ManagementObject]$Disk
		)
		$ImageManagementService = Get-ANImageManagementService -ComputerName $Disk.__SERVER
		$State = $ImageManagementService.GetVirtualHardDiskState($Disk.HostResource[0])
		if($null -ne $State)
		{
			try
			{
				$XMLData = [xml]$State.State
				if($XmlData.SelectSingleNode('/INSTANCE/@CLASSNAME').Value -ne 'Msvm_VirtualHardDiskState')
				{
					throw('Data is not of type Msvm_VirtualHardDiskState')
				}
			}
			catch
			{
				Write-Host ('Error parsing state information for {0}: {1}' -f $Disk.HostResource[0], $_)
				Exit 2
			}
			$RawAlignment = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Alignment'']/VALUE/child::text()').Value
			$RawFileSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''FileSize'']/VALUE/child::text()').Value
			$RawFragmentationPercentage = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''FragmentationPercentage'']/VALUE/child::text()').Value
			$RawInUse = $XmlData.SelectSingleNode('//PROPERTY[@NAME = ''InUse'']/VALUE/child::text()').Value
			$RawMinInternalSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''MinInternalSize'']/VALUE/child::text()').Value
			$RawPhysicalSectorSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''PhysicalSectorSize'']/VALUE/child::text()').Value
		  
			try
			{
				$WMIStateData = ([wmiclass]('\\{0}\root\virtualization\v2:Msvm_VirtualHardDiskState' -f $Disk.__SERVER)).CreateInstance()
			}
			catch
			{
				Write-Host ('Unable to create a disk state object: {0}' -f $_)
				Exit 2
			}

			$WMIStateData.Alignment = $RawAlignment
			$WMIStateData.FileSize = $RawFileSize
			$WMIStateData.FragmentationPercentage = $RawFragmentationPercentage
			$WMIStateData.InUse = $RawInUse
			$WMIStateData.MinInternalSize = $RawMinInternalSize
			$WMIStateData.PhysicalSectorSize = $RawPhysicalSectorSize
			$WMIStateData
		}
		else
		{
			Write-Host ('Unable to retrieve state information for {0}' -f $Disk.HostResource[0])
			Exit 2
		}
	}
}

C:\Program Files\NSClient++\scripts\anutilitybase.ps1

This script contains functions that will be used by my other scripts. Most will not work without it. This file does not exist and must be created.

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

	Version 1.0 May 17th, 2017

	Intended for use with the NSClient++ module from http://nsclient.org
	Provides reusable functions for other check scripts.
#>
if(-not $ANUtilityBaseIncluded)
{
	$ANUtilityBaseIncluded = $true

	function Get-ANUtilityBaseVersion
	{
		New-Object System.Version(1, 0, 0, 0)
	}

	function Format-ANStorageNumberAsFriendly
	{
		param(
			[Parameter(Position=1)][UInt64]$Number,
			[Parameter(Position=2)][Switch]$AsBits
		)
	 
		$DigitLength = $Number.ToString().Length
		$DigitGrouping = [Math]::Floor($DigitLength / 3)
		$DigitGroupLocatorModulus = $DigitLength % 3
		if($DigitGrouping -gt 0 -and -$DigitGroupLocatorModulus -eq 0)
		{
			$DigitGrouping -= 1
		}
		if($AsBits)
		{
			$Tag = 'b'
		}
		else
		{
			$Tag = 'B'
		}

		switch($DigitGrouping)
		{
			0 { $ShortenedNumber = $Number; $Suffix = ''	}
			1 { $ShortenedNumber = $Number / 1KB; $Suffix = 'K' }
			2 { $ShortenedNumber = $Number / 1MB; $Suffix = 'M' }
			3 { $ShortenedNumber = $Number / 1GB; $Suffix = 'G' }
			4 { $ShortenedNumber = $Number / 1TB; $Suffix = 'T' }
			default { $ShortenedNumber = $Number / 1PB; $Suffix = 'P' }
		}
		'{0:N2} {1}{2}' -f $ShortenedNumber, $Suffix, $Tag
	}

	function Format-ANNumberAsPercent
	{
		param([Parameter(Position=1)]$Number)
		'{0:N2}%' -f ($Number * 100)
	}

	function Get-ANIsClustered
	{
		[bool](Get-WmiObject -Namespace root -Class '__NAMESPACE' -Filter 'Name="MSCluster"')
	}
	Set-Alias -Name ANIsClustered -Value Get-ANIsClustered
}

 

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!