Solutions provided by the OP5 Monitor Community for the benefit of other clients. These solutions or documents are NOT maintained, tested or supported by ITRS Client Services and just provided as they are written by the original submitter.
Version
This article was written for version 7.0 of OP5 Monitor, it could work on both lower and higher version if nothing else is stated. Articles in the Community-Space are not supported by OP5 Client Services.
About
This document describes how to build custom tools for executing remote commands using the HTTP API. You may download the script that is created and use without warranty or support. You should read through the guide to understand the script and how it could be extended. PHP is used as the scripting language in the examples here, though the ideas can be transposed to other languages. Python examples are also given in the online API documentation.
The OP5 Monitor API is the recommended and supported way of communicating with OP5 Monitor from external sources.
Why use the HTTP API when we have NSCA available?
The Nagios Service Check Acceptor (NSCA) is a tool for submitting passive check results to Nagios or Naemon. As a result, it will bypass the authentication layers of OP5 Monitor.
By contrast the HTTP API is will use the OP5 authentication as it essentially mirrors the function of the web interface. Additionally, OP5 Monitor extends the functionality of Naemon and therefore provides commands not available using NSCA.
A Command Line Example
The API documentation can be found on your OP5 monitor via the web interface using the url with your resolvable hostname:
If you navigate to the API documentation and click the Command link in the left-side menu you will then see a list of commands. Selecting the PROCESS_SERVICE_CHECK_RESULT link will then display details of how to submit a passive check result for services. There are examples for PHP, Python and plain shell using curl.
The curl example from the web page is repeated here below, with placeholders that would need to be replaced with actual data.
curl -u '<your username>:<your password>' -H 'content-type: application/json' -d '{"host_name":"string","service_description":"string","status_code":"int","plugin_output":"string"}' 'https://<monitor-server>/api/command/PROCESS_SERVICE_CHECK_RESULT'
This is clearly a long-winded command to type out and it is expected that users would script and modularise their API requests.
Creating a reusable script
Note! All the example scripts below are outside the bounds of OP5 support.
In the first instance we will create a tool for the explicit process_service_check command and then gradually build a more generic tool.
The following example can only submit the PROCESS_SERVICE_CHECK_RESULT command and does not validate inputs to the script, which can result in unexpected errors.
#!/usr/bin/php
<?php
/**
* This script can only run the PROCESS_SERVICE_CHECK_RESULT, i.e. send a passive
* check on a service. It does so far not handle any possible PHP errors that may
* occur on faulty input. But given that you run:
*
* ./example1.php monitor "Zombie processes" 0 "OK: Everything is fine and dandy"
*
* It will execute properly, and set the service to state 0 (i.e. OK) with the
* output "OK: Everything is fine and dandy".
*/
// To keep static information separated and easily accessible when customizing the
// script for a new host or user we set monitor host, user and password here.define('MONITOR_HOST', '<your monitor host>');
define('MONITOR_USER', '<your monitor user>');
define('MONITOR_PASS', '<your monitor pass>');// We will send the data to the HTTP API as JSON, adding the data given from the command-line
// which is stored in the $argv variable in PHP.
$data = json_encode(array( "host_name" => $argv[1], "service_description" => $argv[2], "status_code
" => intval($argv[3]), "plugin_output" => $argv[4]));
$a_handle = curl_init('https://' . MONITOR_HOST . '/api/command/PROCESS_SERVICE_CHECK_RESULT');// Tell the API that this is JSON
curl_setopt($a_handle, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));// Tell the API who we are
curl_setopt($a_handle, CURLOPT_USERPWD, MONITOR_USER . ':' . MONITOR_PASS);// Tell curl that this is a HTTP POST
curl_setopt($a_handle, CURLOPT_POST, 1);// Tell curl that we want to see the result of the request
curl_setopt($a_handle, CURLOPT_RETURNTRANSFER, TRUE);// And give curl the data we are about to send
curl_setopt($a_handle, CURLOPT_POSTFIELDS, $data);// By default monitor is installed with a self-signed certificate, if you have a proper
// SSL cert. you may remove this line(s), otherwise you need to keep it.
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($a_handle, CURLOPT_SSL_VERIFYPEER, false);// Execute the curl request and json decode the result$result = curl_exec($a_handle);
$result = json_decode($result, true);/**
* This script relies on the monitor HTTP API to handle errors and return them
* in a printable format. This could write to a log instead of printing depending
* on your needs.
*
* Errors from API POST's contain an "error" and "full_error" member, successes
* contain a "result" member.
*/
if ($result['error']) {
echo $result['error'] . "\n";
echo $result['full_error'] . "\n";
exit(1);
} elseif ($result['result']) { echo $result['result'] . "\n";
echo sprintf("On service '%s' of host '%s'\n", $argv[2], $argv[1]);
}
"ex1.php" 62 lines, 2612 bytes written
This next example has more advanced PHP scripting that makes it extensible to support commands other than the submission of passive check results.
example2.php
#!/usr/bin/php<?php
/**
* This script can run the PROCESS_SERVICE_CHEK_RESULT and PROCESS_HOST_CHECK_RESULT
* based on parameters given, that is given you submitted host AND service name or
* simply the host name. The first submits a service result, the second a host
* result.
*
* ./example2.php "monitor;Zombie processes" 0 "OK: Everything is fine and dandy"
* ./example2.php "monitor" 0 "UP: Everything is fine and dandy"
*
* It also has some failsafes for improper or forgotten input which it handles by
* setting this parameters to types which are not allowed for that field in the HTTP
* API, the API will supply a proper error message when executing.
*
* plugin_output is not required for the command so executing:
*
* ./example2.php "monitor" 0
*
* Will be successfull and the output will be set to empty.
*/define('MONITOR_HOST', '<your monitor host>');
define('MONITOR_USER', '<your monitor user>');
define('MONITOR_PASS', '<your monitor pass>');/**
* This script takes the host and service identifiers in naemon/nagios style,
* separated by a semicolon. i.e. "host;service"
*/$key = explode(';', $argv[1]);
$host = $key[0];// This is the ternary operator, I will use it during these scripts
// for setting values or defaults, in simple terms think of them as
// (if) ? then : else, in this case if $key[1] isset, assign that to
// $service else assign false to service, since no service description
// was supplied.$service = (isset($key[1])) ? $key[1] : false;
/**
* Validate that status_code and plugin_output are set, if status_code is not an
* integer set it to an invalid value so that the API returns an error.
*/
$state = (isset($argv[2]) && is_numeric($argv[2])) ? intval($argv[2]) : false;
$output = (isset($argv[3])) ? $argv[3] : false;
$data = array( "host_name" => $host, "status_code" => $state, "plugin_output" => $output);
// Only add "service_description" if this is a service requestif ($service) {
$data['service_description'] = $service;
}
// Select command based on whether a service was given or not
$command = ($service) ? 'PROCESS_SERVICE_CHECK_RESULT' : 'PROCESS_HOST_CHECK_RESULT';
// Build the URL from MONITOR_HOST name and determined $command
$url = sprintf('https://%s/api/command/%s', MONITOR_HOST, $command);
$data = json_encode($data);/**
* This part is the example presented in the API documentation
*/$a_handle = curl_init($url);
curl_setopt($a_handle, CURLOPT_USERPWD, MONITOR_USER . ':' . MONITOR_PASS);
curl_setopt($a_handle, CURLOPT_POST, 1);
curl_setopt($a_handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($a_handle, CURLOPT_POSTFIELDS, $data);
curl_setopt($a_handle, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($a_handle, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($a_handle);
$result = json_decode($result, true);/**
* This script relies on the monitor HTTP API to handle errors and return them
* in a printable format. This could write to a log instead of printing depending
* on your needs.
*/
if ($result['error']) { echo $result['error'] . "\n";
echo $result['full_error'] . "\n";
exit(1);
} elseif ($result['result']) { echo $result['result'] . "\n";
echo sprintf("On service '%s' of host '%s'\n", $service, $host);
}
As can be seen in the above script we have two functions that are closely tied with the action they perform, service_result and host_result, the invocation of these is dynamic, based on the context (service or host) the script was called, and which action was supplied ( e.g. "result"). Given this we can easily add another of these functions to perform a different command, for example acknowledge, which is incorporated in this 3rd example below.
op5remote.php
#!/usr/bin/php
<?php
/**
* ./remote.php result "monitor;Zombie processes" 0 "Some output"
*/define('MONITOR_HOST', 'rocky01');
define('MONITOR_USER', 'administrator');
define('MONITOR_PASS', 'd-t-s1927');
define('MONITOR_SSL', false); // Set to true if when your monitor server has a valid SSL cert.// A length of 3 is equal to the script name, action and identifier, the least
// the least required amount of data.if (count($argv) < 3) {
echo "Monitor Remote expects at least two parameters supplied, an action and an identifier\n";
exit(1);
}/**
* Generalized curl execution function that only takes the command to execute
* and the data to send. The request are very similar between commands so we
* abstract the actual HTTP call into this function.
*
* @param string $command The command to use
* @param array $data The data to send * @return void
*/function remote_call ($command, array $data) {
// Build the URL based on configured host and what command to send
$url = sprintf('https://%s/api/command/%s', MONITOR_HOST, $command);
$jsondata = json_encode($data);
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_USERPWD, MONITOR_USER . ':' . MONITOR_PASS);
curl_setopt($handle, CURLOPT_POST, 1);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle, CURLOPT_POSTFIELDS, $jsondata);
curl_setopt($handle, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));if (MONITOR_SSL === false) {
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
}
$result = curl_exec($handle);if ($result) {
$result = json_decode($result, true);
if ($result['error']) {
echo $result['error'] . "\n";
echo $result['full_error'] . "\n";
exit(1);
} elseif ($result['result']) {
echo $result['result'] . "\n";
echo "Using data: \n";
array_walk($data, function ($v, $k) {
echo sprintf(" %s : %s\n", $k, $v);
});
}
} else {
echo "Failed to execute cURL request\n";
echo curl_error($handle) . "\n";
exit(1);
}
}/**
* Monitor remote functions.
*
* This section contains the functions that handle context specific behaviours.
*//**
* Submits a passive service check result using the op5 Monitor
* PROCESS_SERVICE_CHECK_RESULT endpoint of the HTTP API
*
* @param string $host The host
* @param string $service The service
* @param array $parameters The parameters to use
* @return void
*/function service_result ($host, $service, $parameters) {
$state = (isset($parameters[0]) && is_numeric($parameters[0])) ? intval($parameters[0]) : false;
$output = (isset($parameters[1])) ? $parameters[1] : '';
remote_call('PROCESS_SERVICE_CHECK_RESULT', array( "host_name" => $host, "service_description" => $service, "status_code" => $state, "plugin_output" => $output ));
}/**
* Submits a passive host check result using the op5 Monitor
* PROCESS_HOST_CHECK_RESULT endpoint of the HTTP API
*
* @param string $host The host
* @param array $parameters The parameters to use
* @return void
*/
function host_result ($host, $parameters) {
$state = (isset($parameters[0]) && is_numeric($parameters[0])) ? intval($parameters[0]) : false;
$output = (isset($parameters[1])) ? $parameters[1] : '';
remote_call('PROCESS_SERVICE_CHECK_RESULT', array( "host_name" => $host, "status_code" => $state, "plugin_output" => $output ));
}/**
* Submits an acknowledge to op5 Monitor ACKNOWLEDGE_HOST_PROBLEM
* endpoint of the HTTP API
*
* @param string $host The host
* @param array $parameters The parameters to use
* @return void
*/function host_ack ($host, $parameters)
{
$comment = (isset($parameters[0])) ? $parameters[0] : 'Acknowledged by Monitor Remote';
remote_call('ACKNOWLEDGE_HOST_PROBLEM', array( "host_name" => $host, "comment" => $comment, "sticky" => 1, "notify" => true, "persistent" => true ));
}/**
* Submits an acknowledge to op5 Monitor ACKNOWLEDGE_SVC_PROBLEM
* endpoint of the HTTP API
*
* @param string $host The host
* @param string $service The service
* @param array $parameters The parameters to use
* @return void
*/function service_ack ($host, $service, $parameters) {
$comment = (isset($parameters[0])) ? $parameters[0] : 'Acknowledged by Monitor Remote';
remote_call('ACKNOWLEDGE_SVC_PROBLEM', array( "host_name" => $host, "service_description" => $service, "comment" => $comment, "sticky" => 1, "notify" => true, "persistent" => true ));
}
/**
* Identify required parameters, action and identifier, and invoke proper function
* for the execution.
*/$action = $argv[1];
$identifier = explode(';', $argv[2]);
$host = $identifier[0];
$service = (isset($identifier[1])) ? $identifier[1] : false;
$parameters = array_slice($argv, 3);
$context = ($service) ? 'service' : 'host';
$caller = strtolower($context . '_' . $action);if (function_exists($caller)) {
if ($service) {
call_user_func_array($caller, array($host, $service, $parameters));
} else {
call_user_func_array($caller, array($host, $parameters));
}
} else {
echo sprintf("No action '%s' on context '%s' available\n", $action, $context);
exit(1);
}
Summary
With simple scripts accessing the OP5 API you can perform and automate many functions that you would otherwise need to access the web gui for.
Examples
Examples using the above op5remote php script.
Acknowledge hosts
op5remote ack "host" "My comment"
Acknowledge services
op5remote ack "host;service" "My comment"
Submit passive host results
op5remote result "host;service" 0 "This host is UP"
Submit passive service results
op5remote result "host;service" 0 "This service is OK"
Comments
0 comments
Please sign in to leave a comment.