Nagios Services

- Moved check-services.php to a poller module
    - Added performance data collection to the poller
    - Centralised DB functions to includes/services.inc.php
    - Created add/edit/delete functions off the device, services page
    - Removed legacy edit/delete interfaces.
    - Moved and modified check.inc scripts
    - Documentation Updates
    - Modified services table
This commit is contained in:
Aaron Daniels
2016-03-15 22:16:08 +10:00
parent 2d2f56c3dc
commit 0d6cfec589
61 changed files with 1040 additions and 802 deletions

View File

@@ -1,59 +0,0 @@
#!/usr/bin/env php
<?php
/*
* Observium
*
* This file is part of Observium.
*
* @package observium
* @subpackage services
* @author Adam Armstrong <adama@memetic.org>
* @copyright (C) 2006 - 2012 Adam Armstrong
*/
chdir(dirname($argv[0]));
require 'includes/defaults.inc.php';
require 'config.php';
require 'includes/definitions.inc.php';
require 'includes/functions.php';
foreach (dbFetchRows('SELECT * FROM `devices` AS D, `services` AS S WHERE S.device_id = D.device_id ORDER by D.device_id DESC') as $service) {
if ($service['status'] = '1') {
unset($check, $service_status, $time, $status);
$service_status = $service['service_status'];
$service_type = strtolower($service['service_type']);
$service_param = $service['service_param'];
$checker_script = $config['install_dir'].'/includes/services/'.$service_type.'/check.inc';
if (is_file($checker_script)) {
include $checker_script;
}
else {
$cmd = $config['nagios_plugins'] . "/check_" . $service['service_type'] . " -H " . ($service['service_ip'] ? $service['service_ip'] : $service['hostname']);
$cmd .= " ".$service['service_param'];
$check = shell_exec($cmd);
list($check, $time) = explode("|", $check);
if(stristr($check, "ok -")) {
$status = 1;
}
else {
$status = 0;
}
}
$update = array();
if ($service_status != $status) {
$update['service_changed'] = time();
}
$update = array_merge(array('service_status' => $status, 'service_message' => $check, 'service_checked' => time()), $update);
dbUpdate($update, 'services', '`service_id` = ?', array($service['service_id']));
unset($update);
}
else {
$status = '0';
}//end if
} //end foreach

View File

@@ -22,31 +22,29 @@ $config['nagios_plugins'] = "/usr/lib/nagios/plugins";
This will point LibreNMS at the location of the nagios plugins - please ensure that any plugins you use are set to executable.
Finally, you now need to add check-services.php to the current cron file (/etc/cron.d/librenms typically) like:
```bash
*/5 * * * * librenms /opt/librenms/check-services.php >> /dev/null 2>&1
```
Now you can add services via the main Services link in the navbar, or via the 'Add Service' link within the device, services page.
Now you can add services via the main Services link in the navbar, or via the Services link within the device page.
## Performance data
> **Please note that at present the service checks will only return the status and the response from the check
no graphs will be generated. **
By default, the poller module will collect all performance data that the check script returns and display each datasource on a separate graph.
However for some modules it would be better if some of this information was consolidated on a single graph.
An example is the ICMP check. This check returns: Round Trip Average (rta), Round Trip Min (rtmin) and Round Trip Max (rtmax).
These have been combined onto a single graph.
## Supported checks
If you find a check script that would benefit from having some datasources graphed together, please log an issue on GitHub with the debug information from the poller, and let us know which DS's should go together. Example below:
- ftp
- icmp
- spop
- ssh
- ssl_cert
- http
- domain_expire
- mysql
- imap
- dns
- telnet
- smtp
- pop
- simap
- ntp
- ircd
Nagios Service - 26
Request: /usr/lib/nagios/plugins/check_icmp localhost
Perf Data - DS: rta, Value: 0.016, UOM: ms
Perf Data - DS: pl, Value: 0, UOM: %
Perf Data - DS: rtmax, Value: 0.044, UOM: ms
Perf Data - DS: rtmin, Value: 0.009, UOM: ms
Response: OK - localhost: rta 0.016ms, lost 0%
Service DS: {
"rta": "ms",
"pl": "%",
"rtmax": "ms",
"rtmin": "ms"
}
OK u:0.00 s:0.00 r:40.67
RRD[update /opt/librenms/rrd/localhost/services-26.rrd N:0.016:0:0.044:0.009]

View File

@@ -0,0 +1,47 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2016 Aaron Daniels <aaron@daniels.id.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
if (is_admin() === false) {
die('ERROR: You need to be admin');
}
$service_id = $_POST['service_id'];
$type = mres($_POST['stype']);
$desc = mres($_POST['desc']);
$ip = mres($_POST['ip']);
$param = mres($_POST['param']);
$device_id = mres($_POST['device_id']);
if (is_numeric($service_id) && $service_id > 0) {
// Need to edit.
$update = array('service_desc' => $desc, 'service_ip' => $ip, 'service_param' => $param);
if (service_edit($update, $service_id)) {
$status = array('status' =>0, 'message' => 'Modified Service: <i>'.$service_id.': '.$type.'</i>');
}
else {
$status = array('status' =>1, 'message' => 'ERROR: Failed to modify service: <i>'.$service_id.'</i>');
}
}
else {
// Need to add.
$service_id = service_add($device_id, $type, $desc, $ip, $param);
if ($service_id == false) {
$status = array('status' =>1, 'message' => 'ERROR: Failed to add Service: <i>'.$type.'</i>');
}
else {
$status = array('status' =>0, 'message' => 'Added Service: <i>'.$service_id.': '.$type.'</i>');
}
}
header('Content-Type: application/json');
echo _json_encode($status);

View File

@@ -0,0 +1,31 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2016 Aaron Daniels <aaron@daniels.id.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
if (is_admin() === false) {
$status = array('status' =>1, 'message' => 'ERROR: You need to be admin to delete services');
}
else {
if (!is_numeric($_POST['service_id'])) {
$status = array('status' =>1, 'message' => 'No Service has been selected');
}
else {
if (service_delete($_POST['service_id'])) {
$status = array('status' =>0, 'message' => 'Service: <i>'.$_POST['service_id'].', has been deleted.</i>');
}
else {
$status = array('status' =>1, 'message' => 'Service: <i>'.$_POST['service_id'].', has NOT been deleted.</i>');
}
}
}
header('Content-Type: application/json');
echo _json_encode($status);

View File

@@ -0,0 +1,33 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2016 Aaron Daniels <aaron@daniels.id.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
if (is_admin() === false) {
die('ERROR: You need to be admin');
}
$service_id = $_POST['service_id'];
if (is_numeric($service_id) && $service_id > 0) {
$service = service_get(null, $service_id);
$output = array(
'stype' => $service[0]['service_type'],
'ip' => $service[0]['service_ip'],
'desc' => $service[0]['service_desc'],
'param' => $service[0]['service_param']
);
header('Content-Type: application/json');
echo _json_encode($output);
}

View File

@@ -0,0 +1,97 @@
<?php
/*
* LibreNMS module to display graphing for Nagios Service
*
* Copyright (c) 2016 Aaron Daniels <aaron@daniels.id.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
// Get a list of all services for this device.
require_once '../includes/services.inc.php';
$services = service_get($device['device_id']);
// Determine which key is the service we want to show.
if (isset($vars['service'])) {
// Service is set, find its key.
foreach ($services as $key => $service) {
if ($service['service_id'] == $vars['service']) {
// We have found the service we want.
$vars['service'] = $key;
}
}
}
else {
// No service set, set the first one.
if (isset($services[0])) {
$vars['service'] = 0;
}
}
// We know our service. build the filename.
$filename = "services-".$services[$vars['service']]['service_id'].".rrd";
$rrd_filename = $config['rrd_dir'] . "/" . $device['hostname'] . "/" . safename ($filename);
// if we have a script for this check, use it.
$check_script = $config['install_dir'].'/includes/services/check_'.strtolower($services[$vars['service']]['service_type']).'.inc.php';
if (is_file($check_script)) {
include $check_script;
// If we have a replacement DS use it.
if (isset($check_ds)) {
$services[$vars['service']]['service_ds'] = $check_ds;
}
}
include "includes/graphs/common.inc.php";
$rrd_options .= " -l 0 -E ";
$rrd_options .= " COMMENT:' Now Avg Max\\n'";
$rrd_additions = "";
// Remove encoded characters
$services[$vars['service']]['service_ds'] = htmlspecialchars_decode($services[$vars['service']]['service_ds']);
if ($services[$vars['service']]['service_ds'] != "") {
$graphinfo = json_decode($services[$vars['service']]['service_ds'],TRUE);
// Do we have a DS set
if (!isset($graphinfo[$vars['ds']])) {
foreach ($graphinfo as $k => $v) {
// Select a DS to display.
$vars['ds'] = $k;
}
}
// Need: DS name, Label
$ds = $vars['ds'];
$label = $graphinfo[$vars['ds']];
if (file_exists($rrd_filename)) {
if (isset($check_graph)) {
// We have a graph definition, use it.
$rrd_additions .= $check_graph[$ds];
}
else {
// Build the graph ourselves
$color = $config['graph_colours']['mixed'][2];
$rrd_additions .= " DEF:DS=" . $rrd_filename . ":".$ds.":AVERAGE ";
$rrd_additions .= " AREA:DS#" . $color . ":'" . str_pad(substr(ucfirst($ds)." (".$label.")",0,15),15) . "' ";
$rrd_additions .= " GPRINT:DS:LAST:%5.2lf%s ";
$rrd_additions .= " GPRINT:DS:AVERAGE:%5.2lf%s ";
$rrd_additions .= " GPRINT:DS:MAX:%5.2lf%s\\\l ";
}
}
}
if ($rrd_additions == "") {
// We didn't add any data points.
}
else {
$rrd_options .= $rrd_additions;
}

View File

@@ -0,0 +1,75 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2016 Aaron Daniels <aaron@daniels.id.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
if(is_admin() === false) {
die('ERROR: You need to be admin');
}
?>
<div class="modal fade" id="confirm-delete" tabindex="-1" role="dialog" aria-labelledby="Delete" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h5 class="modal-title" id="Delete">Confirm Delete</h5>
</div>
<div class="modal-body">
<p>Please confirm that you would like to delete this service.</p>
</div>
<div class="modal-footer">
<form role="form" class="remove_token_form">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger danger" id="service-removal" data-target="service-removal">Delete</button>
<input type="hidden" name="service_id" id="service_id" value="">
<input type="hidden" name="confirm" id="confirm" value="yes">
</form>
</div>
</div>
</div>
</div>
<script>
$('#confirm-delete').on('show.bs.modal', function(e) {
service_id = $(e.relatedTarget).data('service_id');
$("#service_id").val(service_id);
});
$('#service-removal').click('', function(e) {
e.preventDefault();
var service_id = $("#service_id").val();
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: { type: "delete-service", service_id: service_id },
success: function(result){
if (result.status == 0) {
// Yay.
$('#message').html('<div class="alert alert-info">' + result.message + '</div>');
$("#row_"+service_id).remove();
$("#"+service_id).remove();
$("#confirm-delete").modal('hide');
}
else {
// Nay.
$("#message").html('<div class="alert alert-danger">'+result.message+'</div>');
$("#confirm-delete").modal('hide');
}
},
error: function(){
$("#message").html('<div class="alert alert-info">An error occurred deleting this service.</div>');
$("#confirm-delete").modal('hide');
}
});
});
</script>

View File

@@ -0,0 +1,145 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2016 Aaron Daniels <aaron@daniels.id.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
if(is_admin() !== false) {
// Build the types list.
if ($handle = opendir($config['nagios_plugins'])) {
while (false !== ($file = readdir($handle))) {
if ($file != '.' && $file != '..' && !strstr($file, '.') && strstr($file, 'check_')) {
list(,$check_name) = explode('_',$file,2);
$stype .= "<option value='$check_name'>$check_name</option>";
}
}
closedir($handle);
}
?>
<div class="modal fade bs-example-modal-sm" id="create-service" tabindex="-1" role="dialog" aria-labelledby="Create" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h5 class="modal-title" id="Create">Services</h5>
</div>
<div class="modal-body">
<form method="post" role="form" id="service" class="form-horizontal service-form">
<input type="hidden" name="service_id" id="service_id" value="">
<input type="hidden" name="device_id" id="device_id" value="<?=$device['device_id']?>">
<input type="hidden" name="type" id="type" value="create-service">
<div class="form-service">
<div class="col-sm-12">
<span id="ajax_response">&nbsp;</span>
</div>
</div>
<div class="form-service">
<label for='stype' class='col-sm-3 control-label'>Type: </label>
<div class="col-sm-9">
<select id='stype' name='stype' placeholder='type' class='form-control has-feedback'>
<?=$stype?>
</select>
</div>
</div>
<div class='form-service'>
<label for='desc' class='col-sm-3 control-label'>Description: </label>
<div class='col-sm-9'>
<input type='text' id='desc' name='desc' class='form-control'/>
</div>
</div>
<div class="form-service">
<label for='ip' class='col-sm-3 control-label'>IP Address: </label>
<div class="col-sm-9">
<input type='text' id='ip' name='ip' class='form-control has-feedback' placeholder='<?=$device['hostname']?>'/>
</div>
</div>
<div class="form-service">
<label for='param' class='col-sm-3 control-label'>Parameters: </label>
<div class="col-sm-9">
<input type='text' id='param' name='param' class='form-control has-feedback' placeholder=''/>
</div>
</div>
<div class="form-service">
<div class="col-sm-offset-3 col-sm-9">
<button class="btn btn-success btn-sm" type="submit" name="service-submit" id="service-submit" value="save">Save Service</button>
</div>
</div>
<div class="clearfix"></div>
</form>
</div>
</div>
</div>
</div>
<script>
// on-hide
$('#create-service').on('hide.bs.modal', function (event) {
$('#stype').val('');
$("#stype").prop("disabled", false);
$('#ip').val('');
$('#desc').val('');
$('#param').val('');
});
// on-load
$('#create-service').on('show.bs.modal', function (e) {
var button = $(e.relatedTarget);
var service_id = button.data('service_id');
var modal = $(this)
$('#service_id').val(service_id);
$.ajax({
type: "POST",
url: "ajax_form.php",
data: { type: "parse-service", service_id: service_id },
dataType: "json",
success: function(output) {
$('#stype').val(output['stype']);
$("#stype").prop("disabled", true);
$('#ip').val(output['ip']);
$('#desc').val(output['desc']);
$('#param').val(output['param']);
}
});
});
// on-submit
$('#service-submit').click('', function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: "ajax_form.php",
data: $('form.service-form').serialize(),
success: function(result){
if (result.status == 0) {
// Yay.
$("#create-service").modal('hide');
$('#message').html('<div class="alert alert-info">' + result.message + '</div>');
setTimeout(function() {
location.reload(1);
}, 1500);
}
else {
// Nay.
$("#ajax_response").html('<div class="alert alert-danger">'+result.message+'</div>');
}
},
error: function(){
$("#ajax_response").html('<div class="alert alert-info">An error occurred creating this service.</div>');
}
});
});
</script>
<?php
}

View File

@@ -3,7 +3,7 @@ require $config['install_dir'].'/includes/object-cache.inc.php';
// FIXME - this could do with some performance improvements, i think. possible rearranging some tables and setting flags at poller time (nothing changes outside of then anyways)
$service_alerts = dbFetchCell("SELECT COUNT(service_id) FROM services WHERE service_status = '0'");
$service_status = service_status();
$if_alerts = dbFetchCell("SELECT COUNT(port_id) FROM `ports` WHERE `ifOperStatus` = 'down' AND `ifAdminStatus` = 'up' AND `ignore` = '0'");
if ($_SESSION['userlevel'] >= 5) {
@@ -219,18 +219,20 @@ if ($config['show_services']) {
<?php
if ($service_alerts) {
echo('
<li role="presentation" class="divider"></li>
<li><a href="services/state=down/"><i class="fa fa-bell-o fa-fw fa-lg"></i> Alerts ('.$service_alerts.')</a></li>');
if (($service_status[0] > 0) || ($service_status[2] > 0)) {
echo ' <li role="presentation" class="divider"></li>';
if ($service_status[2] > 0) {
echo ' <li><a href="services/state=warning/"><i class="fa fa-bell-o fa-col-warning fa-fw fa-lg"></i> Warning ('.$service_status[2].')</a></li>';
}
if ($service_status[0] > 0) {
echo ' <li><a href="services/state=critical/"><i class="fa fa-bell-o fa-col-danger fa-fw fa-lg"></i> Critical ('.$service_status[0].')</a></li>';
}
}
if ($_SESSION['userlevel'] >= '10') {
echo('
<li role="presentation" class="divider"></li>
<li><a href="addsrv/"><i class="fa fa-cog fa-col-success fa-fw fa-lg"></i> Add Service</a></li>
<li><a href="editsrv/"><i class="fa fa-cog fa-col-primary fa-fw fa-lg"></i> Edit Service</a></li>
<li><a href="delsrv/"><i class="fa fa-cog fa-col-danger fa-fw fa-lg"></i> Delete Service</a></li>');
<li><a href="addsrv/"><i class="fa fa-cog fa-col-success fa-fw fa-lg"></i> Add Service</a></li>');
}
?>
</ul>

View File

@@ -1,36 +0,0 @@
<?php
if (isset($_POST['service']) && is_numeric($_POST['service'])) {
$service = dbFetchRow('SELECT * FROM `services` WHERE `service_id`=?', array($_POST['service']));
echo "
<h3><span class='label label-primary threeqtr-width'>Edit Service</span></h3>
<form id='confirm-editsrv' name='confirm-editsrv' method='post' action='' class='form-horizontal' role='form'>
<input type='hidden' name='device' value='".$service['device_id']."'>
<input type='hidden' name='service' value='".$service['service_id']."'>
<div class='well well-lg'>
<div class='form-group'>
<label for='descr' class='col-sm-2 control-label'>Description</label>
<div class='col-sm-5'>
<textarea name='descr' id='descr' class='form-control input-sm' rows='5'>".$service['service_desc']."</textarea>
</div>
</div>
<div class='form-group'>
<label for='ip' class='col-sm-2 control-label'>IP Address</label>
<div class='col-sm-5'>
<input name='ip' id='ip' value='".$service['service_ip']."' class='form-control input-sm' placeholder='IP Address'>
</div>
</div>
<div class='form-group'>
<label for='params' class='col-sm-2 control-label'>Parameters</label>
<div class='col-sm-5'>
<input name='params' id='params' value='".$service['service_param']."' class='form-control input-sm'>
</div>
<div class='col-sm-5'>
This may be required based on the service check.
</div>
</div>
<button type='submit' id='confirm-editsrv' name='confirm-editsrv' value='yes' class='btn btn-primary input-sm'>Edit Service</button>
</div>
</form>";
}//end if

View File

@@ -1,77 +0,0 @@
<?php
if (!$samehost) {
if ($bg == $list_colour_a) {
$bg = $list_colour_b;
}
else {
$bg = $list_colour_a;
}
}
$service_type = strtolower($service['service_type']);
if ($service[service_status] == '0') {
$status = "<span class=red><b>$service_type</b></span>";
}
else if ($service[service_status] == '1') {
$status = "<span class=green><b>$service_type</b></span>";
}
else if ($service[service_status] == '2') {
$status = "<span class=grey><b>$service_type</b></span>";
}
$message = trim($service['service_message']);
$message = str_replace("\n", '<br />', $message);
$desc = trim($service['service_desc']);
$desc = str_replace("\n", '<br />', $desc);
$since = (time() - $service['service_changed']);
$since = formatUptime($since);
if ($service['service_checked']) {
$checked = (time() - $service['service_checked']);
$checked = formatUptime($checked);
}
else {
$checked = 'Never';
}
$mini_url = 'graph.php?id='.$service['service_id'].'&amp;type=service_availability&amp;from='.$config['time']['day'].'&amp;to='.$config['time']['now'].'&amp;width=80&amp;height=20&amp;bg=efefef';
$popup = "onmouseover=\"return overlib('<div class=list-large>".$device['hostname'].' - '.$service['service_type'];
$popup .= "</div><img src=\'graph.php?id=".$service['service_id'].'&amp;type=service_availability&amp;from='.$config['time']['day'].'&amp;to='.$config['time']['now']."&amp;width=400&amp;height=125\'>";
$popup .= "', RIGHT".$config['overlib_defaults'].');" onmouseout="return nd();"';
echo "
<tr>";
if ($device_id) {
if (!$samehost) {
echo "<td>".generate_device_link($device).'</span></td>';
}
else {
echo '<td></td>';
}
}
echo "
<td>
$status
</td>
<td>
$since
</td>
<td>
<span class='box-desc'>$message</span>
</td>
<td>
<span class='box-desc'>$desc</span>
</td>
<td>
<span class='box-desc'>$checked</span>
</td>
</tr>";
$i++;

View File

@@ -1,10 +0,0 @@
<?php
$updated = '1';
$service_id = add_service(mres($_POST['device']), mres($_POST['type']), mres($_POST['descr']), mres($_POST['ip']), mres($_POST['params']));
if ($service_id) {
$message .= $message_break.'Service added ('.$service_id.')!';
$message_break .= '<br />';
}

View File

@@ -1,10 +0,0 @@
<?php
$updated = '1';
$affected = dbDelete('services', '`service_id` = ?', array($_POST['service']));
if ($affected) {
$message .= $message_break.$rows.' service deleted!';
$message_break .= '<br />';
}

View File

@@ -1,5 +0,0 @@
<?php
$updated = '1';
$updated = edit_service(mres($_POST['service']), mres($_POST['descr']), mres($_POST['ip']), mres($_POST['params']));

View File

@@ -8,9 +8,7 @@ else {
if ($_SESSION['userlevel'] >= '10') {
$updated = '1';
// FIXME should call add_service (needs more parameters)
$service_id = dbInsert(array('device_id' => $_POST['device'], 'service_ip' => $_POST['ip'], 'service_type' => $_POST['type'], 'service_desc' => $_POST['descr'], 'service_param' => $_POST['params'], 'service_ignore' => '0', 'service_status' => '0', 'service_checked' => '0', 'service_changed' => '0', 'service_message' => 'New check', 'service_disabled' => '0'), 'services');
$service_id = service_add($_POST['device'], $_POST['type'], $_POST['descr'], $_POST['ip'], $_POST['params'], 0);
if ($service_id) {
$message .= $message_break.'Service added ('.$service_id.')!';
$message_break .= '<br />';

View File

@@ -1,48 +0,0 @@
<?php
if ($_SESSION['userlevel'] < '5') {
include 'includes/error-no-perm.inc.php';
}
else {
$pagetitle[] = 'Delete service';
if ($_POST['delsrv']) {
if ($_SESSION['userlevel'] > '5') {
include 'includes/service-delete.inc.php';
}
}
foreach (dbFetchRows('SELECT * FROM `services` AS S, `devices` AS D WHERE S.device_id = D.device_id ORDER BY hostname') as $device) {
$service_description = '';
if (!empty($device['service_desc'])) {
$service_description = ' - ' . substr($device['service_desc'], 0, 30);
}
$servicesform .= "<option value='".$device['service_id']."'>".$device['hostname'].' - '.$device['service_type'].$service_description.'</option>';
}
if ($updated) {
print_message('Service Deleted!');
}
echo "
<h4>Delete Service</h4>
<form id='addsrv' name='addsrv' method='post' action='' class='form-horizontal' role='form'>
<input type=hidden name='delsrv' value='yes'>
<div class='well well-lg'>
<div class='form-group'>
<label for='service' class='col-sm-2 control-label'>Device - Service - Description</label>
<div class='col-sm-5'>
<select name='service' id='service' class='form-control input-sm'>
$servicesform
</select>
</div>
<div class='col-sm-5'>
</div>
</div>
<button type='submit' name='Submit' class='btn btn-danger input-sm'>Delete</button>
</div>
</form>";
}//end if

View File

@@ -3,30 +3,24 @@
if (is_admin() === true || is_read() === true) {
if ($_POST['addsrv']) {
if ($_SESSION['userlevel'] >= '10') {
include 'includes/service-add.inc.php';
}
}
$updated = '1';
if ($_POST['delsrv']) {
if ($_SESSION['userlevel'] >= '10') {
include 'includes/service-delete.inc.php';
}
}
if ($_POST['confirm-editsrv']) {
echo 'yeah';
if ($_SESSION['userlevel'] >= '10') {
include 'includes/service-edit.inc.php';
}
}
if ($handle = opendir($config['install_dir'].'/includes/services/')) {
while (false !== ($file = readdir($handle))) {
if ($file != '.' && $file != '..' && !strstr($file, '.')) {
$servicesform .= "<option value='$file'>$file</option>";
$service_id = service_add($_POST['device'], $_POST['type'], $_POST['descr'], $_POST['ip'], $_POST['params'], 0);
if ($service_id) {
$message .= $message_break.'Service added ('.$service_id.')!';
$message_break .= '<br />';
}
}
}
// Build the types list.
if ($handle = opendir($config['nagios_plugins'])) {
while (false !== ($file = readdir($handle))) {
if ($file != '.' && $file != '..' && !strstr($file, '.') && strstr($file, 'check_')) {
list(,$check_name) = explode('_',$file,2);
$servicesform .= "<option value='$check_name'>$check_name</option>";
}
}
closedir($handle);
}
@@ -37,45 +31,6 @@ if (is_admin() === true || is_read() === true) {
print_message('Device Settings Saved');
}
if (dbFetchCell('SELECT COUNT(*) from `services` WHERE `device_id` = ?', array($device['device_id'])) > '0') {
$i = '1';
foreach (dbFetchRows('select * from services WHERE device_id = ? ORDER BY service_type', array($device['device_id'])) as $service) {
$existform .= "<option value='".$service['service_id']."'>".$service['service_type'].'</option>';
}
}
echo '<div class="row">';
if ($existform) {
echo '<div class="col-sm-6">';
if ($_POST['editsrv'] == 'yes') {
include_once 'includes/print-service-edit.inc.php';
}
else {
echo "
<h3><span class='label label-info threeqtr-width'>Edit / Delete Service</span></h3>
<form method='post' action='' class='form-horizontal'>
<div class='well well-lg'>
<div class='form-group'>
<label for='service' class='col-sm-2 control-label'>Type: </label>
<div class='col-sm-4'>
<select name='service' class='form-control input-sm'>
$existform
</select>
</div>
</div>
<div class='form-group'>
<div class='col-sm-offset-2 col-sm-4'>
<button type='submit' class='btn btn-primary btn-sm' name='editsrv' id='editsrv' value='yes'>Edit</button> <button type='submit' class='btn btn-danger btn-sm' name='delsrv' id='delsrv' value='yes'>Delete</button>
</div>
</div>
</div>
</form>";
}
echo '</div>';
}
echo '<div class="col-sm-6">';
include_once 'includes/print-service-add.inc.php';

View File

@@ -7,12 +7,10 @@ $ports['up'] = dbFetchCell("SELECT COUNT(*) FROM `ports` WHERE device_id =
$ports['down'] = dbFetchCell("SELECT COUNT(*) FROM `ports` WHERE device_id = ? AND `ifOperStatus` = 'down' AND `ifAdminStatus` = 'up'", array($device['device_id']));
$ports['disabled'] = dbFetchCell("SELECT COUNT(*) FROM `ports` WHERE device_id = ? AND `ifAdminStatus` = 'down'", array($device['device_id']));
$services['total'] = dbFetchCell("SELECT COUNT(service_id) FROM `services` WHERE `device_id` = ?", array($device['device_id']));
$services['up'] = dbFetchCell("SELECT COUNT(service_id) FROM `services` WHERE `device_id` = ? AND `service_status` = '1' AND `service_ignore` ='0'", array($device['device_id']));
$services['down'] = dbFetchCell("SELECT COUNT(service_id) FROM `services` WHERE `device_id` = ? AND `service_status` = '0' AND `service_ignore` = '0'", array($device['device_id']));
$services['disabled'] = dbFetchCell("SELECT COUNT(service_id) FROM `services` WHERE `device_id` = ? AND `service_ignore` = '1'", array($device['device_id']));
$services = service_status($device['device_id']);
$services['total'] = array_sum($services);
if ($services['down']) {
if ($services[0]) {
$services_colour = $warn_colour_a;
}
else {

View File

@@ -1,49 +1,44 @@
<?php
if ($services['total']) {
echo '<div class="container-fluid">';
echo '<div class="row">
<div class="col-md-12">
<div class="panel panel-default panel-condensed">
<div class="panel-heading">';
echo "<img src='images/16/cog.png'><strong> Services</strong>";
echo ' </div>
<table class="table table-hover table-condensed table-striped">';
echo "
<tr>
<td><img src='images/16/cog.png'> $services[total]</td>
<td><img src='images/16/cog_go.png'> $services[up]</td>
<td><img src='images/16/cog_error.png'> $services[down]</td>
<td><img src='images/16/cog_disable.png'> $services[disabled]</td>
</tr>
<tr>
<td colspan='4'>";
foreach (dbFetchRows('SELECT * FROM services WHERE device_id = ? ORDER BY service_type', array($device['device_id'])) as $data) {
if ($data['service_status'] == '0' && $data['service_ignore'] == '1') {
$status = 'grey';
}
if ($data['service_status'] == '1' && $data['service_ignore'] == '1') {
$status = 'green';
}
if ($data['service_status'] == '0' && $data['service_ignore'] == '0') {
// Build the string.
foreach (service_get ($device['device_id']) as $data) {
if ($data['service_status'] == '1') {
// Ok
$status = 'green';
} elseif ($data['service_status'] == '0') {
// Critical
$status = 'red';
} elseif ($data['service_status'] == '2') {
// Warning
$status = 'red';
} else {
// Unknown
$status = 'grey';
}
if ($data['service_status'] == '1' && $data['service_ignore'] == '0') {
$status = 'blue';
}
echo "$break<a class=$status>".strtolower($data['service_type']).'</a>';
$string .= $break . '<a class=' . $status . '>' . strtolower ($data['service_type']) . '</a>';
$break = ', ';
}
echo '</td></tr></table>';
echo '</div>';
echo '</div>';
echo '</div>';
echo '</div>';
}//end if
?>
<div class="container-fluid">
<div class="row col-md-12">
<div class="panel panel-default panel-condensed">
<div class="panel-heading">
<img src='images/16/cog.png'><strong> Services</strong>
</div>
<table class="table table-hover table-condensed table-striped">
<tr>
<td title="Total"><img src='images/16/cog.png'> <?=$services['total']?></td>
<td title="Status - Ok"><img src='images/16/cog_add.png'> <?=$services[1]?></td>
<td title="Status - Critical"><img src='images/16/cog_delete.png'> <?=$services[0]?></td>
<td title="Status - Unknown"><img src='images/16/cog_error.png'> <?=$services[2]?></td>
</tr>
<tr>
<td colspan='4'><?=$string?></td>
</tr>
</table>
</div>
</div>
</div>
<?php
}

View File

@@ -1,5 +1,14 @@
<?php print_optionbar_start();
<?php
$pagetitle[] = 'Services';
require_once '../includes/services.inc.php';
$services = service_get($device['device_id']);
require_once 'includes/modal/new_service.inc.php';
require_once 'includes/modal/delete_service.inc.php';
print_optionbar_start();
echo "<span style='font-weight: bold;'>Services</span> &#187; ";
$menu_options = array(
@@ -29,43 +38,85 @@ foreach ($menu_options as $option => $text) {
$sep = ' | ';
}
unset($sep);
echo '<div class="pull-right"><a data-toggle="modal" href="#create-service"><img src="images/16/add.png" border="0" align="absmiddle"> Add Service</a></div>';
print_optionbar_end();
if (dbFetchCell('SELECT COUNT(service_id) FROM `services` WHERE device_id = ?', array($device['device_id'])) > '0') {
echo "<div style='margin: 5px;'><table cellpadding=7 border=0 cellspacing=0 width=100%>";
$i = '1';
foreach (dbFetchRows('SELECT * FROM `services` WHERE `device_id` = ? ORDER BY `service_type`', array($device['device_id'])) as $service) {
include 'includes/print-service.inc.php';
?>
<div class="row col-sm-12"><span id="message"></span></div>
<?php
if (count($services) > '0') {
// Loop over each service, pulling out the details.
?>
<table class="table table-hover table-condensed table-striped">
<?php
foreach ($services as $service) {
$service['service_ds'] = htmlspecialchars_decode($service['service_ds']);
if ($service['service_status'] == 1) {
$status = "<span class='green'>Ok</span>";
}
elseif ($service['service_status'] == 2) {
$status = "<span class='red'>Warning</span>";
}
elseif ($service['service_status'] == 0) {
$status = "<span class='red'>Critical</span>";
}
else {
$status = "<span class='grey'>Unknown</span>";
}
?>
<tr id="row_<?=$service['service_id']?>">
<td>
<div class="col-sm-12">
<div class="col-sm-2"><?=$service['service_type']?></div>
<div class="col-sm-6"><?=$service['service_desc']?></div>
<div class="col-sm-2"><?=$status?></div>
<div class="pull-right">
<button type='button' class='btn btn-primary btn-sm' aria-label='Edit' data-toggle='modal' data-target='#create-service' data-service_id='<?=$service['service_id']?>' name='edit-service'><span class='glyphicon glyphicon-pencil' aria-hidden='true'></span></button>
<button type='button' class='btn btn-danger btn-sm' aria-label='Delete' data-toggle='modal' data-target='#confirm-delete' data-service_id='<?=$service['service_id']?>' name='delete-service'><span class='glyphicon glyphicon-trash' aria-hidden='true'></span></button>
</div>
</div>
<div class="col-sm-12">
<div class="col-sm-8"><?=nl2br(trim($service['service_message']))?></div>
<div class="col-sm-4"><?=formatUptime(time() - $service['service_changed'])?></div>
</div>
<?php
if ($vars['view'] == 'details') {
$graph_array['height'] = '100';
$graph_array['width'] = '210';
$graph_array['to'] = $config['time']['now'];
$graph_array['id'] = $service['service_id'];
$graph_array['type'] = 'service_availability';
// if we have a script for this check, use it.
$check_script = $config['install_dir'].'/includes/services/check_'.strtolower($service['service_type']).'.inc.php';
if (is_file($check_script)) {
include $check_script;
$periods = array(
'day',
'week',
'month',
'year',
);
// If we have a replacement DS use it.
if (isset($check_ds)) {
$service['service_ds'] = $check_ds;
}
}
echo '<tr style="background-color: '.$bg.'; padding: 7px;"><td colspan=4>';
include 'includes/print-graphrow.inc.php';
echo '</td></tr>';
$graphs = json_decode($service['service_ds'],TRUE);
foreach ($graphs as $k => $v) {
$graph_array['device'] = $device['device_id'];
$graph_array['type'] = 'device_service';
$graph_array['service'] = $service['service_id'];
$graph_array['ds'] = $k;
?>
<div class="col-sm-12">
<?php
include 'includes/print-graphrow.inc.php';
?>
</div>
<?php
}
}
}
echo '</table></div>';
?>
</td>
</tr>
</table>
<?php
}
else {
echo 'No Services';
?>
<div class='row col-sm-12'>No Services</div>
<?php
}
$pagetitle[] = 'Services';
?>

View File

@@ -1,52 +0,0 @@
<?php
if (is_admin() === false && is_read() === false) {
include 'includes/error-no-perm.inc.php';
}
else {
$pagetitle[] = 'Edit service';
if ($_POST['confirm-editsrv']) {
if ($_SESSION['userlevel'] > '5') {
include 'includes/service-edit.inc.php';
}
}
foreach (dbFetchRows('SELECT * FROM `services` AS S, `devices` AS D WHERE S.device_id = D.device_id ORDER BY hostname') as $device) {
$service_description = '';
if (!empty($device['service_desc'])) {
$service_description = ' - ' . substr($device['service_desc'], 0, 30);
}
$servicesform .= "<option value='".$device['service_id']."'>".$device['hostname'].' - '.$device['service_type'].$service_description.'</option>';
}
if ($updated) {
print_message('Service updated!');
}
if ($_POST['editsrv'] == 'yes') {
include_once 'includes/print-service-edit.inc.php';
}
else {
echo "
<h4>Delete Service</h4>
<form id='editsrv' name='editsrv' method='post' action='' class='form-horizontal' role='form'>
<input type=hidden name='delsrv' value='yes'>
<div class='well well-lg'>
<div class='form-group'>
<label for='service' class='col-sm-2 control-label'>Device - Service - Description</label>
<div class='col-sm-5'>
<select name='service' id='service' class='form-control input-sm'>
$servicesform
</select>
</div>
<div class='col-sm-5'>
</div>
</div>
<button type='submit' name='editsrv' id='editsrv' value='yes' class='btn btn-primary input-sm'>Edit</button>
</div>
</form>";
}//end if
}//end if

View File

@@ -9,36 +9,21 @@ echo "<span style='font-weight: bold;'>Services</span> &#187; ";
$menu_options = array(
'basic' => 'Basic',
);
$sql_param = array();
if (isset($vars['state'])) {
if ($vars['state'] == 'up') {
$state = '1';
}
elseif ($vars['state'] == 'down') {
$state = '0';
}
}
if ($vars['state']) {
$where .= " AND service_status= ? AND service_disabled='0' AND `service_ignore`='0'";
$sql_param[] = $state;
}
if ($vars['disabled']) {
$where .= ' AND service_disabled= ?';
$sql_param[] = $vars['disabled'];
}
if ($vars['ignore']) {
$where .= ' AND `service_ignore`= ?';
$sql_param[] = $vars['ignore'];
}
if (!$vars['view']) {
$vars['view'] = 'basic';
}
$status_options = array(
'all' => 'All',
'ok' => 'Ok',
'warning' => 'Warning',
'critical' => 'Critical',
);
if (!$vars['state']) {
$vars['state'] = 'all';
}
// The menu option - on the left
$sep = '';
foreach ($menu_options as $option => $text) {
if (empty($vars['view'])) {
@@ -57,21 +42,60 @@ foreach ($menu_options as $option => $text) {
$sep = ' | ';
}
unset($sep);
// The status option - on the right
echo '<div class="pull-right">';
$sep = '';
foreach ($status_options as $option => $text) {
if (empty($vars['state'])) {
$vars['state'] = $option;
}
echo $sep;
if ($vars['state'] == $option) {
echo "<span class='pagemenu-selected'>";
}
echo generate_link($text, $vars, array('state' => $option));
if ($vars['state'] == $option) {
echo '</span>';
}
$sep = ' | ';
}
unset($sep);
echo '</div>';
print_optionbar_end();
echo '<div class="table-responsive">
<table class="table table-condensed">
<tr>
<th>Device</th>
<th>Service</th>
<th>Changed</th>
<th>Message</th>
<th>Description</th>
<th>Last Check</th>
</tr>';
$sql_param = array();
if (isset($vars['state'])) {
if ($vars['state'] == 'ok') {
$state = '1';
}
elseif ($vars['state'] == 'critical') {
$state = '0';
}
elseif ($vars['state'] == 'warning') {
$state = '2';
}
}
if (isset($state)) {
$where .= " AND service_status= ? AND service_disabled='0' AND `service_ignore`='0'";
$sql_param[] = $state;
}
?>
<div class="row col-sm-12" id="nagios-services">
<table class="table table-hover table-condensed table-striped">
<tr>
<th>Device</th>
<th>Service</th>
<th>Changed</th>
<th>Message</th>
<th>Description</th>
</tr>
<?php
if ($_SESSION['userlevel'] >= '5') {
$host_sql = 'SELECT * FROM devices AS D, services AS S WHERE D.device_id = S.device_id GROUP BY D.hostname ORDER BY D.hostname';
$host_par = array();
@@ -85,6 +109,7 @@ $shift = 1;
foreach (dbFetchRows($host_sql, $host_par) as $device) {
$device_id = $device['device_id'];
$device_hostname = $device['hostname'];
$devlink = generate_device_link($device);
if ($shift == 1) {
array_unshift($sql_param, $device_id);
$shift = 0;
@@ -94,39 +119,28 @@ foreach (dbFetchRows($host_sql, $host_par) as $device) {
}
foreach (dbFetchRows("SELECT * FROM `services` WHERE `device_id` = ? $where", $sql_param) as $service) {
include 'includes/print-service.inc.php';
// $samehost = 1;
if ($vars['view'] == 'details') {
$graph_array['height'] = '100';
$graph_array['width'] = '215';
$graph_array['to'] = $config['time']['now'];
$graph_array['id'] = $service['service_id'];
$graph_array['type'] = 'service_availability';
$periods = array(
'day',
'week',
'month',
'year',
);
echo '<tr style="background-color: '.$bg.'; padding: 5px;"><td colspan=6>';
foreach ($periods as $period) {
$graph_array['from'] = $$period;
$graph_array_zoom = $graph_array;
$graph_array_zoom['height'] = '150';
$graph_array_zoom['width'] = '400';
echo overlib_link('', generate_lazy_graph_tag($graph_array), generate_graph_tag($graph_array_zoom), NULL);
}
echo '</td></tr>';
}//end if
if ($service['service_status'] == '0') {
$status = "<span class='red'><b>".$service['service_type']."</b></span>";
}
else if ($service['service_status'] == '1') {
$status = "<span class='green'><b>".$service['service_type']."</b></span>";
}
else {
$status = "<span class='grey'><b>".$service['service_type']."</b></span>";
}
?>
<tr>
<td><?=$devlink?></td>
<td><?=$status?></td>
<td><?=formatUptime(time() - $service['service_changed'])?></td>
<td><span class='box-desc'><?=nl2br(trim($service['service_message']))?></span></td>
<td><span class='box-desc'><?=nl2br(trim($service['service_desc']))?></span></td>
</tr>
<?php
}//end foreach
unset($samehost);
}//end foreach
echo '</table>
</div>';
?>
</table>
</div>

View File

@@ -585,38 +585,6 @@ function is_valid_hostname($hostname) {
return ctype_alnum(str_replace('_','',str_replace('-','',str_replace('.','',$hostname))));
}
function add_service($device, $service, $descr, $service_ip, $service_param = "", $service_ignore = 0) {
if (!is_array($device)) {
$device = device_by_id_cache($device);
}
if (empty($service_ip)) {
$service_ip = $device['hostname'];
}
$insert = array('device_id' => $device['device_id'], 'service_ip' => $service_ip, 'service_type' => $service,
'service_changed' => array('UNIX_TIMESTAMP(NOW())'), 'service_desc' => $descr, 'service_param' => $service_param, 'service_ignore' => $service_ignore);
return dbInsert($insert, 'services');
}
function edit_service($service, $descr, $service_ip, $service_param = "", $service_ignore = 0) {
if (!is_numeric($service)) {
return false;
}
$update = array('service_ip' => $service_ip,
'service_changed' => array('UNIX_TIMESTAMP(NOW())'),
'service_desc' => $descr,
'service_param' => $service_param,
'service_ignore' => $service_ignore);
return dbUpdate($update, 'services', '`service_id`=?', array($service));
}
/*
* convenience function - please use this instead of 'if ($debug) { echo ...; }'
*/

View File

@@ -715,6 +715,7 @@ $config['poller_modules']['cisco-voice'] = 1;
$config['poller_modules']['cisco-cbqos'] = 1;
$config['poller_modules']['stp'] = 1;
$config['poller_modules']['cisco-otv'] = 1;
$config['poller_modules']['services'] = 1;
// List of discovery modules. Need to be in this array to be
// considered for execution.

View File

@@ -24,7 +24,7 @@ if ($config['discover_services']) {
$split_oid = explode('.', $oid);
$tcp_port = $split_oid[(count($split_oid) - 6)];
if ($known_services[$tcp_port]) {
discover_service($device, $known_services[$tcp_port]);
service_discover($device, $known_services[$tcp_port]);
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
/*
* LibreNMS module to poll Nagios Services
*
* Copyright (c) 2016 Aaron Daniels <aaron@daniels.id.au>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
foreach (dbFetchRows('SELECT * FROM `devices` AS D, `services` AS S WHERE S.device_id = D.device_id AND D.device_id = ? ORDER by D.device_id DESC', array($device['device_id'])) as $service) {
// Run the polling function
service_poll($service);
} //end foreach

View File

@@ -1,13 +1,265 @@
<?php
function service_status($device = null) {
$sql_query = "SELECT service_status, count(service_status) as count FROM services WHERE";
$sql_param = array();
$add = 0;
function discover_service($device, $service) {
if (!is_null($device)) {
// Add a device filter to the SQL query.
$sql_query .= " `device_id` = ?";
$sql_param[] = $device;
$add++;
}
if ($add == 0) {
// No filters, remove " WHERE" -6
$sql_query = substr($sql_query, 0, strlen($sql_query)-6);
}
$sql_query .= " GROUP BY service_status";
d_echo("SQL Query: ".$sql_query);
// $service is not null, get only what we want.
$result = dbFetchRows($sql_query, $sql_param);
// Set our defaults to 0
$service_count = array(0 => 0, 1 => 0, 2 => 0);
// Rebuild the array in a more convenient method
foreach ($result as $v) {
$service_count[$v['service_status']] = $v['count'];
}
d_echo("Service Count by Status: ".print_r($service_count,TRUE)."\n");
return $service_count;
}
function service_add($device, $type, $desc, $ip='localhost', $param = "", $ignore = 0) {
if (!is_array($device)) {
$device = device_by_id_cache($device);
}
if (empty($ip)) {
$ip = $device['hostname'];
}
$insert = array('device_id' => $device['device_id'], 'service_ip' => $ip, 'service_type' => $type, 'service_changed' => array('UNIX_TIMESTAMP(NOW())'), 'service_desc' => $desc, 'service_param' => $param, 'service_ignore' => $ignore, 'service_status' => 3, 'service_message' => 'Service not yet checked');
return dbInsert($insert, 'services');
}
function service_get($device = null, $service = null) {
$sql_query = "SELECT `service_id`,`device_id`,`service_ip`,`service_type`,`service_desc`,`service_param`,`service_ignore`,`service_status`,`service_changed`,`service_message`,`service_disabled`,`service_ds` FROM `services` WHERE";
$sql_param = array();
$add = 0;
d_echo("SQL Query: ".$sql_query);
if (!is_null($service)) {
// Add a service filter to the SQL query.
$sql_query .= " `service_id` = ? AND";
$sql_param[] = $service;
$add++;
}
if (!is_null($device)) {
// Add a device filter to the SQL query.
$sql_query .= " `device_id` = ? AND";
$sql_param[] = $device;
$add++;
}
if ($add == 0) {
// No filters, remove " WHERE" -6
$sql_query = substr($sql_query, 0, strlen($sql_query)-6);
}
else {
// We have filters, remove " AND" -4
$sql_query = substr($sql_query, 0, strlen($sql_query)-4);
}
d_echo("SQL Query: ".$sql_query);
// $service is not null, get only what we want.
$services = dbFetchRows($sql_query, $sql_param);
d_echo("Service Array: ".print_r($services,TRUE)."\n");
return $services;
}
function service_edit($update=array(), $service=null) {
if (!is_numeric($service)) {
return false;
}
return dbUpdate($update, 'services', '`service_id`=?', array($service));
}
function service_delete($service=null) {
if (!is_numeric($service)) {
return false;
}
return dbDelete('services', '`service_id` = ?', array($service));
}
function service_discover($device, $service) {
if (! dbFetchCell('SELECT COUNT(service_id) FROM `services` WHERE `service_type`= ? AND `device_id` = ?', array($service, $device['device_id']))) {
add_service($device, $service, "(Auto discovered) $service");
service_add($device, $service, "(Auto discovered) $service");
log_event('Autodiscovered service: type '.mres($service), $device, 'service');
echo '+';
}
echo "$service ";
}
function service_poll($service) {
global $config, $device;
$update = array();
$old_status = $service['service_status'];
// if we have a script for this check, use it.
$check_script = $config['install_dir'].'/includes/services/check_'.strtolower($service['service_type']).'.inc.php';
if (is_file($check_script)) {
include $check_script;
}
// If we do not have a cmd from the check script, build one.
if (!isset($check_cmd)) {
$check_cmd = $config['nagios_plugins'] . "/check_" . $service['service_type'] . " -H " . ($service['service_ip'] ? $service['service_ip'] : $service['hostname']);
$check_cmd .= " " . $service['service_param'];
}
// Some debugging
d_echo("\nNagios Service - ".$service['service_id']."\n");
d_echo("Request: ".$check_cmd."\n");
list($status, $msg, $perf) = service_check($check_cmd);
d_echo("Response: ".$msg."\n");
// TODO: Use proper Nagios service status. 0=Ok,1=Warning,2=Critical,Else=Unknown
// Not now because we dont want to break existing alerting rules.
if ($status == 0) {
// Nagios 0 = Libre 1 - Ok
$new_status = 1;
}
elseif ($status == 1) {
// Nagios 1 = Libre 2 - Warning
$new_status = 2;
}
elseif ($status == 2) {
// Nagios 2 = Libre 0 - Critical
$new_status = 0;
}
else {
// Unknown
$new_status = 2;
}
// If we have performance data we will store it.
if (count($perf) > 0) {
// Yes, We have perf data.
$filename = "services-".$service['service_id'].".rrd";
$rrd_filename = $config['rrd_dir'] . "/" . $device['hostname'] . "/" . safename ($filename);
// Set the DS in the DB if it is blank.
$DS = array();
foreach ($perf as $k => $v) {
$DS[$k] = $v['uom'];
}
d_echo("Service DS: "._json_encode($DS)."\n");
if ($service['service_ds'] == "") {
$update['service_ds'] = json_encode($DS);
}
// Create the RRD
if (!file_exists ($rrd_filename)) {
$rra = "";
foreach ($perf as $k => $v) {
if ($v['uom'] == 'c') {
// This is a counter, create the DS as such
$rra .= " DS:".$k.":COUNTER:600:0:U";
}
else {
// Not a counter, must be a gauge
$rra .= " DS:".$k.":GAUGE:600:0:U";
}
}
rrdtool_create ($rrd_filename, $rra . $config['rrd_rra']);
}
// Update RRD
$rrd = array();
foreach ($perf as $k => $v) {
$rrd[$k] = $v['value'];
}
rrdtool_update ($rrd_filename, $rrd);
}
if ($old_status != $new_status) {
// Status has changed, update.
$update['service_changed'] = time();
$update['service_status'] = $new_status;
$update['service_message'] = $msg;
}
if (count($update) > 0) {
service_edit($update,$service['service_id']);
}
return true;
}
function service_check($command) {
// This array is used to test for valid UOM's to be used for graphing.
// Valid values from: https://nagios-plugins.org/doc/guidelines.html#AEN200
// Note: This array must be decend from 2 char to 1 char so that the search works correctly.
$valid_uom = array ('us', 'ms', 'KB', 'MB', 'GB', 'TB', 'c', 's', '%', 'B');
// Make our command safe.
$command = escapeshellcmd($command);
// Run the command and return its response.
exec($command, $response_array, $status);
// exec returns an array, lets implode it back to a string.
$response_string = implode("\n", $response_array);
// Split out the response and the performance data.
list($response, $perf) = explode("|", $response_string);
// Split each performance metric
$perf_arr = explode(' ', $perf);
// Create an array for our metrics.
$metrics = array();
// Loop through the perf string extracting our metric data
foreach ($perf_arr as $string) {
// Separate the DS and value: DS=value
list ($ds,$values) = explode('=', trim($string));
// Keep the first value, discard the others.
list($value,,,) = explode(';', trim($values));
$value = trim($value);
// Set an empty uom
$uom = '';
// is the UOM valid - https://nagios-plugins.org/doc/guidelines.html#AEN200
foreach ($valid_uom as $v) {
if ((strlen($value)-strlen($v)) === strpos($value,$v)) {
// Yes, store and strip it off the value
$uom = $v;
$value = substr($value, 0, -strlen($v));
break;
}
}
if ($ds != "") {
// We have a DS. Add an entry to the array.
d_echo("Perf Data - DS: ".$ds.", Value: ".$value.", UOM: ".$uom."\n");
$metrics[$ds] = array ('value'=>$value, 'uom'=>$uom);
}
else {
// No DS. Don't add an entry to the array.
d_echo("Perf Data - None.\n");
}
}
return array ($status, $response, $metrics);
}

View File

@@ -4,14 +4,4 @@
if ($service['service_param']) { $nsquery = $service['service_param']; } else { $nsquery = "localhost"; }
if ($service['service_ip']) { $resolver = $service['service_ip']; } else { $resolver = $service['hostname']; }
$check = shell_exec($config['nagios_plugins'] . "/check_dns -H ".$nsquery." -s ".$resolver);
list($check, $time) = explode("|", $check);
if(strstr($check, "DNS OK: ")) {
$status = '1';
} else {
$status = '0';
}
?>
$check_cmd = $config['nagios_plugins'] . "/check_dns -H ".$nsquery." -s ".$resolver;

View File

@@ -0,0 +1,10 @@
<?php
#Get check_domain from https://raw.githubusercontent.com/glensc/nagios-plugin-check_domain/master/check_domain.sh
$check_cmd = $config['nagios_plugins'] . "/check_domain -d ";
if( $service['service_ip'] ) {
$check_cmd .= $service['service_ip'];
} else {
$check_cmd .= $service['hostname'];
}
$check_cmd .= " ".$service['service_param'];

View File

@@ -0,0 +1,3 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_ftp -H ".$service['hostname'];

View File

@@ -0,0 +1,3 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_http -H ".$service['hostname']." ".$service['service_param'];

View File

@@ -0,0 +1,30 @@
<?php
// check_cmd is the command that is run to execute the check
$check_cmd = $config['nagios_plugins'] . "/check_icmp ".($service['service_ip'] ? $service['service_ip'] : $service['hostname']);
// Check DS is a json array of the graphs that are available
$check_ds = '{"rtt":"s","pl":"%"}';
// Build the graph data
$check_graph = array();
$check_graph['rtt'] = " DEF:DS0=" . $rrd_filename . ":rta:AVERAGE ";
$check_graph['rtt'] .= " LINE1.25:DS0#" . $config['graph_colours']['mixed'][0] . ":'" . str_pad(substr("Round Trip Average",0,15),15) . "' ";
$check_graph['rtt'] .= " GPRINT:DS0:LAST:%5.2lf%s ";
$check_graph['rtt'] .= " GPRINT:DS0:AVERAGE:%5.2lf%s ";
$check_graph['rtt'] .= " GPRINT:DS0:MAX:%5.2lf%s\\\l ";
$check_graph['rtt'] .= " DEF:DS1=" . $rrd_filename . ":rtmax:AVERAGE ";
$check_graph['rtt'] .= " LINE1.25:DS1#" . $config['graph_colours']['mixed'][1] . ":'" . str_pad(substr("Round Trip Max",0,15),15) . "' ";
$check_graph['rtt'] .= " GPRINT:DS1:LAST:%5.2lf%s ";
$check_graph['rtt'] .= " GPRINT:DS1:AVERAGE:%5.2lf%s ";
$check_graph['rtt'] .= " GPRINT:DS1:MAX:%5.2lf%s\\\l ";
$check_graph['rtt'] .= " DEF:DS2=" . $rrd_filename . ":rtmin:AVERAGE ";
$check_graph['rtt'] .= " LINE1.25:DS2#" . $config['graph_colours']['mixed'][2] . ":'" . str_pad(substr("Round Trip Min",0,15),15) . "' ";
$check_graph['rtt'] .= " GPRINT:DS2:LAST:%5.2lf%s ";
$check_graph['rtt'] .= " GPRINT:DS2:AVERAGE:%5.2lf%s ";
$check_graph['rtt'] .= " GPRINT:DS2:MAX:%5.2lf%s\\\l ";
$check_graph['pl'] = " DEF:DS0=" . $rrd_filename . ":pl:AVERAGE ";
$check_graph['pl'] .= " AREA:DS0#" . $config['graph_colours']['mixed'][2] . ":'" . str_pad(substr("Packet Loss (%)",0,15),15) . "' ";
$check_graph['pl'] .= " GPRINT:DS0:LAST:%5.2lf%s ";
$check_graph['pl'] .= " GPRINT:DS0:AVERAGE:%5.2lf%s ";
$check_graph['pl'] .= " GPRINT:DS0:MAX:%5.2lf%s\\\l ";

View File

@@ -0,0 +1,3 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_imap -H ".$service['hostname'];

View File

@@ -0,0 +1,3 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_ircd -H ".$service['hostname']." ".$service['service_param'];

View File

@@ -0,0 +1,5 @@
<?php
// provide some sane default
if ($service['service_param']) { $dbname = $service['service_param']; } else { $dbname = "mysql"; }
$check_cmd = $config['nagios_plugins'] . "/check_mysql -H ".$service['hostname']." ".$dbname;

View File

@@ -0,0 +1,2 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_ntp -H ".$service['hostname']." ".$service['service_param'];

View File

@@ -0,0 +1,2 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_pop -H ".$service['hostname'];

View File

@@ -0,0 +1,2 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_simap -H ".$service['hostname'];

View File

@@ -0,0 +1,2 @@
<?php
$check_cmd = shell_exec($config['nagios_plugins'] . "/check_smtp -H ".$service['hostname']);

View File

@@ -0,0 +1,2 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_spop -H ".$service['hostname'];

View File

@@ -0,0 +1,2 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_ssh -H ".$service['hostname']." ".$service['service_param'];

View File

@@ -0,0 +1,8 @@
<?php
$check_cmd = $config['nagios_plugins'] . "/check_ssl_cert -H ";
if( !empty($service['service_ip']) ) {
$check_cmd .= $service['service_ip'];
} else {
$check_cmd .= $service['hostname'];
}
$check_cmd .= " ".$service['service_param'];

View File

@@ -0,0 +1,3 @@
<?php
if($service['service_port']) { $port = $service['service_port']; } else { $port = '23'; }
$check_cmd = $config['nagios_plugins'] . "/check_telnet -H ".$service['hostname']." -p ".$port;

View File

@@ -1,21 +0,0 @@
<?php
#Get check_domain from https://raw.githubusercontent.com/glensc/nagios-plugin-check_domain/master/check_domain.sh
$cmd = $config['nagios_plugins'] . "/check_domain -d ";
if( $service['service_ip'] ) {
$cmd .= $service['service_ip'];
} else {
$cmd .= $service['hostname'];
}
$cmd .= " ".$service['service_param'];
$check = shell_exec($cmd);
list($check, $time) = explode("|", $check);
if(strstr($check, "OK - Domain")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_ftp -H ".$service['hostname']);
list($check, $time) = explode("|", $check);
if(strstr($check, "FTP OK - ")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_http -H ".$service['hostname']." ".$service['service_param']);
list($check, $time) = explode("|", $check);
if(strstr($check, "HTTP OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,12 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_icmp ".($service['service_ip'] ? $service['service_ip'] : $service['hostname']));
list($check, $time) = explode("|", $check);
if(strstr($check, "OK - ")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_imap -H ".$service['hostname']);
list($check, $time) = explode("|", $check);
if(strstr($check, "IMAP OK - ")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_ircd -H ".$service['hostname']." ".$service['service_param']);
list($check, $time) = explode("|", $check);
if (strstr($check, "IRCD ok")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,16 +0,0 @@
<?php
// provide some sane default
if ($service['service_param']) { $dbname = $service['service_param']; } else { $dbname = "mysql"; }
$check = shell_exec($config['nagios_plugins'] . "/check_mysql -H ".$service['hostname']." ".$dbname);
list($check, $time) = explode("|", $check);
if(strstr($check, "Uptime:") || strstr($check, "MySQL OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_ntp -H ".$service['hostname']." ".$service['service_param']);
list($check, $time) = explode("|", $check);
if(strstr($check, "NTP OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_pop -H ".$service['hostname']);
list($check, $time) = explode("|", $check);
if(strstr($check, "POP OK - ")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_simap -H ".$service['hostname']);
list($check, $time) = explode("|", $check);
if(strstr($check, "SIMAP OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_smtp -H ".$service['hostname']);
list($check, $time) = explode("|", $check);
if(strstr($check, "SMTP OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_spop -H ".$service['hostname']);
list($check, $time) = explode("|", $check);
if(strstr($check, "SPOP OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,13 +0,0 @@
<?php
$check = shell_exec($config['nagios_plugins'] . "/check_ssh -H ".$service['hostname']." ".$service['service_param']);
list($check, $time) = explode("|", $check);
if(strstr($check, "SSH OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,20 +0,0 @@
<?php
$cmd = $config['nagios_plugins'] . "/check_ssl_cert -H ";
if( !empty($service['service_ip']) ) {
$cmd .= $service['service_ip'];
} else {
$cmd .= $service['hostname'];
}
$cmd .= " ".$service['service_param'];
$check = shell_exec($cmd);
list($check, $time) = explode("\|", $check);
if(strstr($check, "SSL_CERT OK")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -1,15 +0,0 @@
<?php
if($service['service_port']) { $port = $service['service_port']; } else { $port = '23'; }
$check = shell_exec($config['nagios_plugins'] . "/check_telnet -H ".$service['hostname']." -p ".$port);
list($check, $time) = explode("|", $check);
if(strstr($check, "TCP OK - ")) {
$status = '1';
} else {
$status = '0';
}
?>

View File

@@ -5,4 +5,3 @@
*/5 * * * * root /opt/librenms/cronic /opt/librenms/poller-wrapper.py 16
15 0 * * * root /opt/librenms/daily.sh >> /dev/null 2>&1
* * * * * root /opt/librenms/alerts.php >> /dev/null 2>&1
*/5 * * * * root /opt/librenms/check-services.php >> /dev/null 2>&1

View File

@@ -5,4 +5,3 @@
*/5 * * * * librenms /opt/librenms/cronic /opt/librenms/poller-wrapper.py 16
15 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1
* * * * * librenms /opt/librenms/alerts.php >> /dev/null 2>&1
*/5 * * * * librenms /opt/librenms/check-services.php >> /dev/null 2>&1

2
sql-schema/107.sql Normal file
View File

@@ -0,0 +1,2 @@
ALTER TABLE `services` ADD `service_ds` VARCHAR(255) NOT NULL COMMENT 'Data Sources available for this service';
ALTER TABLE `services` DROP `service_checked`;