Author: @GordonCole
Revision: v0.1
Tested with:
- Icinga 2 v2.6.3-1
- Icinga Web 2 v2.4.1
- Windows Server 2012 R2
Introduction
A vanilla Windows Icinga2 installation provides access to a number of standard server health and performance metrics. For example hard disk space, CPU, free RAM, or accessing the value of a Windows Performance Counter. Each of these is metrics is measured using a “check”. These are programs called by the main Icinga2 service.
Users may write their own “checks”, as long as they return a result in the expected format (status, performance data, text).
PowerShell has established itself as a powerful way of automating tasks and accessing information on a Windows machine. We can use PowerShell to access server metrics and return data to Icinga2 by writing a suitable PowerShell script.
Configuration
Create a Check Command
Here we define a CheckCommand so that Icinga2 knows the path of the executable to call, in this case the powershell.exe interpreter (a PowerShell session).
This should be defined in commands.conf
object CheckCommand "powershell_check" {
import "plugin-check-command"
command = [ "C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe" ]
arguments = {
"-command" = {
value = "$ps_command$"
order = -1
}
"-warn" = {
value = "$ps_warn$"
}
"-crit" = {
value = "$ps_crit$"
}
";exit" = {
value = "$$LastExitCode"
}
}
}
This will run the 32-bit version of PowerShell. If you want to use the 64-bit version use the following command instead:
command = [ "C:\\Windows\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe" ]
Let’s consider the arguments:
-
-command - this contains a variable which will contain the path to our PowerShell script (our check)
-
-warn - this contains a variable which may be set (elsewhere) to contain a warning threshold value (optional - your script needs to be written to be able to accept arguments)
-
-crit - this contains a variable which may be set (elsewhere) to contain a critical threshold value (optional - your script needs to be written to be able to accept arguments)
-
;exit - we always pass this argument the value “$LastExitCode”. This is not an Icinga2 variable. This argument tells the powershell.exe session to take the exit code generated by your PowerShell script, and use this for the exit code when the session exits. This exit code is important as the plug-in’s service “status” is taken from the exit code (0=OK, 1=Warning, 2=Critical, 3=Unknown). Note also the “;” in the above code. If you omit this, you powershell.exe will aways exit with code “0” and your check wont have the correct status.
-
“\” is used to escape the “\” so we see “\\” in the path name
-
“$” is used to escape the “$” so we see “$$” in the string “$LastExitCode”
If you find the above confusing, just remember that Icinga2 needs to construct a command that you could yourself enter at the command prompt in order to run a PowerShell script. For example:
C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -command "&'C:\Program Files\ICINGA2\sbin\check_reboot.ps1' ;exit $LastExitCode
This is very useful as you can manually test your scripts (“plug ins”) from the command line without involving Icinga2. You cannot, however, see the exit code.
The above puts in place the underlying ability to call PowerShell from Icinga2.
Define a Service
We can define an Icinga2 “service” that references a PowerShell scripts or “plug-ins”. It relies on the check command we defined in the previous step.
For example:
apply Service "reboot_status_check" {
import "generic-service"
display_name = "Reboot Check"
check_command = "powershell_check"
vars.ps_command = "& 'C:\\Program Files\\ICINGA2\\sbin\\check_reboot.ps1'"
command_endpoint = host.address
assign where host.vars.os == "windows"
}
In this case we are using the variable vars.os in the host object definition to apply this service to all our “windows” hosts.
Write PowerShell script (Plug In)
We now require a suitable PowerShell script to act as our “plug in”. Note that monitoring plug-ins should adhere to guidelines regarding what you can pass them, and what they should return. This example may not be fully compliant in this regard.
You should consult https://www.monitoring-plugins.org/doc/guidelines.html for detailed information on writing plugins.
# Checks if RebootRequired key exists, if so returns a warning.
# This key is deleted upon a successful reboot.
# This may indicate that Windows patching has taken place, without a reboot.
# Checks if RebootRequired reg path exists
$value = test-path -path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"
# If path does not exist, return OK status
if ($value -match "False") {
echo "OK - No reboot required"
$returnCode=0
}
# Else return WARNING status
else {
echo "WARNING - Reboot required"
$returnCode=1
}
exit ($returnCode)
To note:
- return code is passed as the “exit” code. This in turn is passed back to Icinga2. This is the “status” of the service check
- This is a simple example and does not include any error handling, which you would normally consider
- We need to save this script on our Windows server in the correct path, as shown in our service definition. This is best placed in the same location as the other Icinga2 Windows checks:
C:\Program Files\ICINGA2\sbin\
The exit codes from the plug-in relate to Icinga2 service status as follows:
- 0 = OK
- 1 = Warning
- 2 = Critical
- 3 = Unknown
Permissions
It should be noted that the ability to run PowerShell may be restricted by group policy.
You should consider the user that will be used to run these scripts and what rights they will need. For example, an Icinga2 service run as “Local System” will therefore run the script as the user “local system”. This user can check the registry but likely wont have rights over an SQL database, for example. Care must be taken when assigning rights.
Conclusion
Once you can harness PowerShell, your abilities to check Windows server health and vital statistics is limited only by your scripting knowledge. You may, for example:
- Check registry keys (some applications store their status, for example “primary” or “stand-by” in the registry)
- Check files are present and updated in particular folders (useful in file processing systems)
- Parse application log files for error codes and generate Icinga2 warnings
You may be able to use a combination of Icinga2 and PowerShell and remove the requirement for other agents such as NSClient++.
FAQ
-
Where do I get more information on installing and using PowerShell?
https://docs.microsoft.com/en-us/powershell/ -
Where can I see some more examples of PowerShell plug-ins?
http://it-wiki.eu/monitoring/icinga2/windows