diff --git a/check-services.php b/check-services.php
deleted file mode 100755
index a39171a3d..000000000
--- a/check-services.php
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env php
-
- * @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
diff --git a/doc/Extensions/Services.md b/doc/Extensions/Services.md
index fe2608552..fa7237cc9 100644
--- a/doc/Extensions/Services.md
+++ b/doc/Extensions/Services.md
@@ -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]
diff --git a/html/includes/forms/create-service.inc.php b/html/includes/forms/create-service.inc.php
new file mode 100644
index 000000000..e2e20a170
--- /dev/null
+++ b/html/includes/forms/create-service.inc.php
@@ -0,0 +1,47 @@
+
+ *
+ * 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: '.$service_id.': '.$type.'');
+ }
+ else {
+ $status = array('status' =>1, 'message' => 'ERROR: Failed to modify service: '.$service_id.'');
+ }
+}
+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: '.$type.'');
+ }
+ else {
+ $status = array('status' =>0, 'message' => 'Added Service: '.$service_id.': '.$type.'');
+ }
+}
+header('Content-Type: application/json');
+echo _json_encode($status);
\ No newline at end of file
diff --git a/html/includes/forms/delete-service.inc.php b/html/includes/forms/delete-service.inc.php
new file mode 100644
index 000000000..fc1f1e8ee
--- /dev/null
+++ b/html/includes/forms/delete-service.inc.php
@@ -0,0 +1,31 @@
+
+ *
+ * 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: '.$_POST['service_id'].', has been deleted.');
+ }
+ else {
+ $status = array('status' =>1, 'message' => 'Service: '.$_POST['service_id'].', has NOT been deleted.');
+ }
+ }
+}
+header('Content-Type: application/json');
+echo _json_encode($status);
diff --git a/html/includes/forms/parse-service.inc.php b/html/includes/forms/parse-service.inc.php
new file mode 100644
index 000000000..f5a1bbb5e
--- /dev/null
+++ b/html/includes/forms/parse-service.inc.php
@@ -0,0 +1,33 @@
+
+ *
+ * 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);
+}
diff --git a/html/includes/graphs/device/service.inc.php b/html/includes/graphs/device/service.inc.php
new file mode 100644
index 000000000..1cbe99e1b
--- /dev/null
+++ b/html/includes/graphs/device/service.inc.php
@@ -0,0 +1,97 @@
+
+ *
+ * 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;
+}
diff --git a/html/includes/modal/delete_service.inc.php b/html/includes/modal/delete_service.inc.php
new file mode 100644
index 000000000..ca2188909
--- /dev/null
+++ b/html/includes/modal/delete_service.inc.php
@@ -0,0 +1,75 @@
+
+ *
+ * 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');
+}
+
+?>
+
+
+
+
+
+
+
Confirm Delete
+
+
+
Please confirm that you would like to delete this service.
+
+
+
+
+
+
+
diff --git a/html/includes/modal/new_service.inc.php b/html/includes/modal/new_service.inc.php
new file mode 100644
index 000000000..e1b973c74
--- /dev/null
+++ b/html/includes/modal/new_service.inc.php
@@ -0,0 +1,145 @@
+
+ *
+ * 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 .= "";
+ }
+ }
+ closedir($handle);
+ }
+
+?>
+
+
';
print_optionbar_end();
-
-if (dbFetchCell('SELECT COUNT(service_id) FROM `services` WHERE device_id = ?', array($device['device_id'])) > '0') {
- echo "
";
- $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';
-
+?>
+
+ '0') {
+ // Loop over each service, pulling out the details.
+?>
+