mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Added Alert Transports Mapping (#8660)
Hello all, I guess this is the second version of a more fully fleshed out alert contact mapping feature. The old one was GH-8507 Transports to convert: - [x] API - [x] Cisco Spark - [x] Elasticsearch - [x] GitLab - [x] Philips Hue - [x] Jira - [x] Mail - [ ] ~~PagerDuty~~ - Requires a callback so leaving for now - [x] Nagios - [x] IRC - [x] Discord - [x] Rocket.chat - [x] Hipchat - [x] Pushover - [x] Boxcar - [x] Telegram - [x] Pushbullet - [x] VictorOps - [x] OpsGenie - [x] Clickatell - [x] PlaySMS - [x] Canopsis - [x] osTicket - [x] Microsoft Teams - [x] SMSEagle - [x] Syslog - [x] Slack The intention is for this feature to have three different levels to it: 1. Alert rule to an alert contact mapping (where the code is at now) 2. Alert rule to an alert group (made up of alert contacts) mapping 3. Alert contact mapping to different transport configurations. There will be three transport configuration types. 1. Default (the configuration that is held in the configs table) 2. None (no transport configuration - will explain later) 3. Other (a configuration that will be defined in a different able) Take Mail transport for example. It can either be of a "default" or "other" configuration. The hope is that in the future, users can send mail from different mail servers if they wish. However, for ciscospark which requires a room ID and an api-token, I've decided that it has no transport configuration. Most likely, every alert contact will contain a different room-id and an api-token - which is why it has the transport config of "none". For other transports : I am not familiar with them, so hopefully the community can add support for these. I can definitely help! To add support for each transport will require several things: - addition to the UI - addition to forms/alert-contacts.inc.php - modifications to its object class Screenshots    I'm not sure if this is the best way to do things, so please let me know if there's a better way to structure the code! Any comments on code/db schema,/UI etc is welcome and encouraged! The UI is heavily based on alert rules (front end is not my strong suit). And parts of the code are based on the code that was written for alert rules. DO NOT DELETE THIS TEXT #### Please note > Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting. - [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/) #### Testers If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
This commit is contained in:
37
LibreNMS/Alert/AlertUtil.php
Normal file
37
LibreNMS/Alert/AlertUtil.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace LibreNMS\Alert;
|
||||
|
||||
class AlertUtil
|
||||
{
|
||||
// Return rule id from alert id
|
||||
private static function getRuleId($alert_id)
|
||||
{
|
||||
$query = "SELECT `rule_id` FROM `alerts` WHERE `id`=?";
|
||||
return dbFetchCell($query, [$alert_id]);
|
||||
}
|
||||
|
||||
// Return all alert transports mapped to a rule (includies transport groups)
|
||||
// @retyurn array [$transport_id $transport_type]
|
||||
public static function getAlertTransports($alert_id)
|
||||
{
|
||||
// Query for list of transport ids
|
||||
$query = "SELECT b.transport_id, b.transport_type FROM alert_transport_map AS a LEFT JOIN alert_transports AS b ON b.transport_id=a.transport_or_group_id WHERE a.target_type='single' AND a.rule_id=? UNION DISTINCT SELECT d.transport_id, d.transport_type FROM alert_transport_map AS a LEFT JOIN alert_transport_groups AS b ON a.transport_or_group_id=b.transport_group_id LEFT JOIN transport_group_transport AS c ON b.transport_group_id=c.transport_group_id LEFT JOIN alert_transports AS d ON c.transport_id=d.transport_id WHERE a.target_type='group' AND a.rule_id=?";
|
||||
$rule_id = self::getRuleId($alert_id);
|
||||
return dbFetchRows($query, [$rule_id, $rule_id]);
|
||||
}
|
||||
|
||||
// Return transports configured as default
|
||||
// @return array [$transport_id $transport_type]
|
||||
public static function getDefaultAlertTransports()
|
||||
{
|
||||
$query = "SELECT transport_id, transport_type FROM alert_transports WHERE is_default=true";
|
||||
return dbFetchRows($query);
|
||||
}
|
||||
|
||||
// Return list of transport types with a default configured
|
||||
public static function getDefaultTransportList()
|
||||
{
|
||||
$query = "SELECT DISTINCT transport_type FROM alert_transports WHERE is_default=true ";
|
||||
return dbFetchColumn($query);
|
||||
}
|
||||
}
|
19
LibreNMS/Alert/Transport.php
Normal file
19
LibreNMS/Alert/Transport.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Alert;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport as TransportInterface;
|
||||
|
||||
abstract class Transport implements TransportInterface
|
||||
{
|
||||
protected $config;
|
||||
|
||||
// Sets config field to an associative array of transport config values
|
||||
public function __construct($transport_id = null)
|
||||
{
|
||||
if (!empty($transport_id)) {
|
||||
$sql = "SELECT `transport_config` FROM `alert_transports` WHERE `transport_id`=?";
|
||||
$this->config = json_decode(dbFetchCell($sql, [$transport_id]), true);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/* Copyright (C) 2014 Daniel Preussker <f0o@devilcode.org>
|
||||
/* Copyright (C) 2014 Daniel Preussker <f0o>
|
||||
* 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
|
||||
@@ -11,11 +11,11 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
* along with this program. If not, see <http>. */
|
||||
|
||||
/**
|
||||
* API Transport
|
||||
* @author f0o <f0o@devilcode.org>
|
||||
* @author f0o <f0o>
|
||||
* @copyright 2014 f0o, LibreNMS
|
||||
* @license GPL
|
||||
* @package LibreNMS
|
||||
@@ -24,16 +24,33 @@
|
||||
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Api implements Transport
|
||||
class Api extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$url = $this->config['api-url'];
|
||||
$method = $this->config['api-method'];
|
||||
$this->contactAPI($obj, $url, $method);
|
||||
}
|
||||
|
||||
private function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $method => $apis) {
|
||||
// var_dump($method); //FIXME: propper debuging
|
||||
foreach ($apis as $api) {
|
||||
// var_dump($api); //FIXME: propper debuging
|
||||
$this->contactAPI($obj, $api, $method);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function contactAPI($obj, $api, $method)
|
||||
{
|
||||
$method = strtolower($method);
|
||||
list($host, $api) = explode("?", $api, 2);
|
||||
foreach ($obj as $k => $v) {
|
||||
$api = str_replace("%" . $k, $method == "get" ? urlencode($v) : $v, $api);
|
||||
@@ -57,7 +74,32 @@ class Api implements Transport
|
||||
return 'HTTP Status code '.$code;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'API Method',
|
||||
'name' => 'api-method',
|
||||
'descr' => 'API Method: GET or POST',
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
'get' => 'get',
|
||||
'get' => 'get'
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => 'API URL',
|
||||
'name' => 'api-url',
|
||||
'descr' => 'API URL',
|
||||
'type' => 'text',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'api-method' => 'in:GET,POST',
|
||||
'api-url' => 'required|url'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -38,17 +38,37 @@
|
||||
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
use LibreNMS\Config;
|
||||
|
||||
class Boxcar implements Transport
|
||||
class Boxcar extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
global $config;
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$boxcar_opts['access_token'] = $this->config['boxcar-token'];
|
||||
foreach (explode(PHP_EOL, $this->config['options']) as $option) {
|
||||
list($k,$v) = explode('=', $option);
|
||||
$boxcar_opts[$k] = $v;
|
||||
}
|
||||
return $this->contactBoxcar($obj, $boxcar_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $api) {
|
||||
$data = array();
|
||||
$this->contactBoxcar($obj, $api);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function contactBoxcar($obj, $api)
|
||||
{
|
||||
$data = [];
|
||||
$data['user_credentials'] = $api['access_token'];
|
||||
$data['notification[source_name]'] = $config['project_id'];
|
||||
$data['notification[source_name]'] = Config::get('project_id', 'librenms');
|
||||
switch ($obj['severity']) {
|
||||
case "critical":
|
||||
$severity = "Critical";
|
||||
@@ -91,13 +111,35 @@ class Boxcar implements Transport
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://new.boxcar.io/api/notifications');
|
||||
curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
$ret = curl_exec($curl);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_exec($curl);
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
if ($code != 201) {
|
||||
var_dump("Boxcar returned error"); //FIXME: proper debugging
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Access Token',
|
||||
'name' => 'boxcar-token',
|
||||
'descr' => 'Boxcar Access Token',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Boxcar Options',
|
||||
'name' => 'boxcar-options',
|
||||
'descr' => 'Boxcar Options',
|
||||
'type' => 'textarea',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'boxcar-token' => 'required',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,23 @@
|
||||
<?php
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Canopsis implements Transport
|
||||
class Canopsis extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['host'] = $this->config['canopsis-host'];
|
||||
$opts['port'] = $this->config['canopsis-port'];
|
||||
$opts['user'] = $this->config['canopsis-user'];
|
||||
$opts['pass'] = $this->config['canopsis-pass'];
|
||||
$opts['vhost'] = $this->config['canopsis-vhost'];
|
||||
}
|
||||
return $this->contactCanopsis($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactCanopsis($obj, $opts)
|
||||
{
|
||||
// Configurations
|
||||
$host = $opts["host"];
|
||||
@@ -68,4 +80,49 @@ class Canopsis implements Transport
|
||||
$conn->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Hostname',
|
||||
'name' => 'canopsis-host',
|
||||
'descr' => 'Canopsis Hostname',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Port Number',
|
||||
'name' => 'canopsis-port',
|
||||
'descr' => 'Canopsis Port Number',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'User',
|
||||
'name' => 'canopsis-user',
|
||||
'descr' => 'Canopsis User',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Password',
|
||||
'name' => 'canopsis-pass',
|
||||
'descr' => 'Canopsis Password',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Vhost',
|
||||
'name' => 'canopsis-vhost',
|
||||
'descr' => 'Canopsis Vhost',
|
||||
'type' => 'text'
|
||||
],
|
||||
],
|
||||
'validation' => [
|
||||
'canopsis-host' => 'required|string',
|
||||
'canopsis-port' => 'required|numeric',
|
||||
'canopsis-user' => 'required|string',
|
||||
'canopsis-pass' => 'required|string',
|
||||
'canopsis-vhost' => 'required|string',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -11,19 +11,31 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Ciscospark implements Transport
|
||||
class Ciscospark extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
$room_id = $opts['roomid'];
|
||||
$token = $opts['token'];
|
||||
$roomId = $opts['roomid'];
|
||||
} else {
|
||||
$room_id = $this->config['room-id'];
|
||||
$token = $this->config['api-token'];
|
||||
}
|
||||
return $this->contactCiscospark($obj, $room_id, $token);
|
||||
}
|
||||
|
||||
public function contactCiscospark($obj, $room_id, $token)
|
||||
{
|
||||
$text = strip_tags($obj['msg']);
|
||||
$data = array(
|
||||
'roomId' => $roomId,
|
||||
$data = array (
|
||||
'roomId' => $room_id,
|
||||
'text' => $text
|
||||
);
|
||||
$token = $token;
|
||||
|
||||
$curl = curl_init();
|
||||
set_curl_proxy($curl);
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://api.ciscospark.com/v1/messages');
|
||||
@@ -38,10 +50,33 @@ class Ciscospark implements Transport
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
|
||||
if ($code != 200) {
|
||||
var_dump("Cisco Spark returned Error, retry later");
|
||||
echo("Cisco Spark returned Error, retry later\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'API Token',
|
||||
'name' => 'api-token',
|
||||
'descr' => 'CiscoSpark API Token',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'RoomID',
|
||||
'name' => 'room-id',
|
||||
'descr' => 'CiscoSpark Room ID',
|
||||
'type' => 'text',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'api-token' => 'required|string',
|
||||
'room-id' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,26 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Clickatell implements Transport
|
||||
class Clickatell extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$clickatell_opts['token'] = $this->config['clickatell-token'];
|
||||
$clickatell_opts['to'] = preg_split('/([,\r\n]+)/', $this->config['clickatell-numbers']);
|
||||
return $this->contactClickatell($obj, $clickatell_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
return $this->contactClickatell($obj, $opts);
|
||||
}
|
||||
|
||||
public static function contactClickatell($obj, $opts)
|
||||
{
|
||||
$url = 'https://platform.clickatell.com/messages/http/send?apiKey=' . $opts['token'] . '&to=' . implode(',', $opts['to']) . '&content=' . urlencode($obj['title']);
|
||||
|
||||
@@ -39,11 +54,32 @@ class Clickatell implements Transport
|
||||
$ret = curl_exec($curl);
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
if ($code > 200) {
|
||||
if ($debug) {
|
||||
var_dump($ret);
|
||||
}
|
||||
return false;
|
||||
return var_dump($ret);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Token',
|
||||
'name' => 'cickatell-token',
|
||||
'descr' => 'Clickatell Token',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Mobile Numbers',
|
||||
'name' => 'clickatell-numbers',
|
||||
'descr' => 'Enter mobile numbers, can be new line or comma separated',
|
||||
'type' => 'textarea',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'clickatell-token' => 'required|string',
|
||||
'clickatell-numbers' => 'required|string',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -25,23 +25,46 @@
|
||||
* Thanks to F0o <f0o@devilcode.org> for creating the Slack transport which is the majority of this code.
|
||||
* Thanks to sdef2 for figuring out the differences needed to make Discord work.
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Discord implements Transport
|
||||
class Discord extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $tmp_api) {
|
||||
$host = $tmp_api['url'];
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$discord_opts['url'] = $this->config['url'];
|
||||
foreach (explode(PHP_EOL, $this->config['options']) as $option) {
|
||||
list($k,$v) = explode('=', $option);
|
||||
$discord_opts['options'][$k] = $v;
|
||||
}
|
||||
return $this->contactDiscord($obj, $discord_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $discord_opts) {
|
||||
$this->contactDiscord($obj, $discord_opts);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function contactDiscord($obj, $discord_opts)
|
||||
{
|
||||
$host = $discord_opts['url'];
|
||||
$curl = curl_init();
|
||||
$discord_msg = strip_tags($obj['msg']);
|
||||
$color = ($obj['state'] == 0 ? '#00FF00' : '#FF0000');
|
||||
$data = array(
|
||||
'username'=>$tmp_api['username'],
|
||||
$data = [
|
||||
'content' => "". $obj['title'] ."\n" . $discord_msg
|
||||
);
|
||||
];
|
||||
if (!empty($discord_opts['options'])) {
|
||||
$data = array_merge($data, $discord_opts['options']);
|
||||
}
|
||||
|
||||
$alert_message = json_encode($data);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
|
||||
set_curl_proxy($curl);
|
||||
@@ -58,7 +81,29 @@ class Discord implements Transport
|
||||
var_dump("Return: " . $ret); //FIXME: propper debuging
|
||||
return 'HTTP Status code ' . $code;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Discord URL',
|
||||
'name' => 'url',
|
||||
'descr' => 'Discord URL',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Options',
|
||||
'name' => 'options',
|
||||
'descr' => 'Enter the config options (format: option=value separated by new lines)',
|
||||
'type' => 'textarea',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'url' => 'required|url',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,13 +23,23 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Dummy implements Transport
|
||||
class Dummy extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
var_dump($obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function contactDummy()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@@ -16,11 +16,23 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Elasticsearch implements Transport
|
||||
class Elasticsearch extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['es_host'] = $this->config['es-host'];
|
||||
$opts['es_port'] = $this->config['es-port'];
|
||||
$opts['es_index'] = $this->config['es-pattern'];
|
||||
$opts['es_proxy'] = $this-> config['es-proxy'];
|
||||
}
|
||||
|
||||
return $this->contactElasticsearch($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactElasticsearch($obj, $opts)
|
||||
{
|
||||
$es_host = '127.0.0.1';
|
||||
$es_port = 9200;
|
||||
@@ -184,4 +196,42 @@ class Elasticsearch implements Transport
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Host',
|
||||
'name' => 'es-host',
|
||||
'descr' => 'Elasticsearch Host',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Port',
|
||||
'name' => 'es-port',
|
||||
'descr' => 'Elasticsearch Port',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Index Pattern',
|
||||
'name' => 'es-pattern',
|
||||
'descr' => 'Elasticsearch Index Pattern',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Use proxy if configured?',
|
||||
'name' => 'es-proxy',
|
||||
'descr' => 'Elasticsearch Proxy',
|
||||
'type' => 'checkbox',
|
||||
'default' => false
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'es-host' => 'required|string',
|
||||
'es-port' => 'required|string',
|
||||
'es-pattern' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,21 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Gitlab implements Transport
|
||||
class Gitlab extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['project-id'] = $this->config['gitlab-id'];
|
||||
$opts['key'] = $this->config['gitlab-key'];
|
||||
$opts['host'] = $this->config['gitlab-host'];
|
||||
}
|
||||
return $this->contactGitlab($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactGitlab($obj, $opts)
|
||||
{
|
||||
// Don't create tickets for resolutions
|
||||
if ($obj['state'] == 0) {
|
||||
@@ -73,4 +83,35 @@ class Gitlab implements Transport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Host',
|
||||
'name' => 'gitlab-host',
|
||||
'descr' => 'Gitlab Host',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Project ID',
|
||||
'name' => 'gitlab-id',
|
||||
'descr' => 'Gitlab Prokect ID',
|
||||
'type'=> 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Personal Access Token',
|
||||
'name' => 'gitlab-key',
|
||||
'descr' => 'Personal Access Token',
|
||||
'type' => 'text',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'gitlab-host' => 'required|string',
|
||||
'gitlab-id' => 'required|string',
|
||||
'gitlab-key' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,14 +23,36 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Hipchat implements Transport
|
||||
class Hipchat extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$hipchat_opts['url'] = $this->config['hipchat-url'];
|
||||
$hipchat_opts['room_id'] = $this->config['hipchat-room-id'];
|
||||
$hipchat_opts['from'] = $this->config['hipchat-from-name'];
|
||||
foreach (explode(PHP_EOL, $this->config['hipchat-options']) as $option) {
|
||||
list($k,$v) = explode('=', $option);
|
||||
$hipchat_opts[$k] = $v;
|
||||
}
|
||||
return $this->contactHipchat($obj, $hipchat_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
// loop through each room
|
||||
foreach ($opts as $option) {
|
||||
$this->contactHipchat($obj, $option);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function contactHipchat($obj, $option)
|
||||
{
|
||||
$version = 1;
|
||||
if (stripos($option['url'], "v2")) {
|
||||
$version = 2;
|
||||
@@ -97,6 +119,40 @@ class Hipchat implements Transport
|
||||
return 'HTTP Status code ' . $code;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'API URL',
|
||||
'name' => 'hipchat-url',
|
||||
'descr' => 'Hipchat API URL',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Room ID',
|
||||
'name' => 'hipchat-room-id',
|
||||
'descr' => 'Hipchat Room ID',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'From Name',
|
||||
'name' => 'hipchat-from-name',
|
||||
'descr' => 'From Name',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Hipchat Options',
|
||||
'name' => 'hipchat-options',
|
||||
'descr' => 'Hipchat Options',
|
||||
'type' => 'textarea',
|
||||
],
|
||||
],
|
||||
'validation' => [
|
||||
'hipchat-url' => 'required|url',
|
||||
'hipchat-room-id' => 'required|numeric',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,16 +23,27 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
/**
|
||||
* The Hue API currently is fairly limited for alerts.
|
||||
* At it's current implementation we can send ['lselect' => "15 second flash", 'select' => "1 second flash"]
|
||||
* If a colour request is sent with it it will permenantly change the colour which is less than desired
|
||||
*/
|
||||
class Hue implements Transport
|
||||
class Hue extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['user'] = $this->config['hue-user'];
|
||||
$opts['bridge'] = $this->config['hue-host'];
|
||||
$opts['duration'] = $this->config['hue-duration'];
|
||||
}
|
||||
|
||||
return $this->contactHue($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactHue($obj, $opts)
|
||||
{
|
||||
// Don't alert on resolve at this time
|
||||
if ($obj['state'] == 0) {
|
||||
@@ -68,4 +79,39 @@ class Hue implements Transport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config'=>[
|
||||
[
|
||||
'title'=> 'Host',
|
||||
'name' => 'hue-host',
|
||||
'descr' => 'Hue Host',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title'=> 'Hue User',
|
||||
'name' => 'hue-user',
|
||||
'descr' => 'Phillips Hue Host',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title'=> 'Duration',
|
||||
'name' => 'hue-duration',
|
||||
'descr' => 'Phillips Hue Duration',
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
'1 Second' => 'select',
|
||||
'15 Seconds' => 'lselect'
|
||||
]
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'hue-host' => 'required|string',
|
||||
'hue-user' => 'required|string',
|
||||
'hue-duration' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,14 +23,19 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
use LibreNMS\Config;
|
||||
|
||||
class Irc implements Transport
|
||||
class Irc extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
global $config;
|
||||
$f = $config['install_dir'] . "/.ircbot.alert";
|
||||
return $this->contactIrc($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactIrc($obj, $opts)
|
||||
{
|
||||
$f = Config::get('install_dir') . "/.ircbot.alert";
|
||||
if (file_exists($f) && filetype($f) == "fifo") {
|
||||
$f = fopen($f, "w+");
|
||||
$r = fwrite($f, json_encode($obj) . "\n");
|
||||
@@ -42,4 +47,22 @@ class Irc implements Transport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'IRC',
|
||||
'name' => 'irc',
|
||||
'descr' => 'Enable IRC alerts',
|
||||
'type' => 'checkbox',
|
||||
'default' => true,
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'irc' => 'required'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,23 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Jira implements Transport
|
||||
class Jira extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['username'] = $this->config['jira-username'];
|
||||
$opts['password'] = $this->config['jira-password'];
|
||||
$opts['prjkey'] = $this->config['jira-key'];
|
||||
$opts['issuetype'] = $this->config['jira-type'];
|
||||
$opts['url'] = $this->config['jira-url'];
|
||||
}
|
||||
return $this->contactJira($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactJira($obj, $opts)
|
||||
{
|
||||
// Don't create tickets for resolutions
|
||||
if ($obj['severity'] == 'recovery' && $obj['msg'] != 'This is a test alert') {
|
||||
@@ -75,4 +87,49 @@ class Jira implements Transport
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'URL',
|
||||
'name' => 'jira-url',
|
||||
'descr' => 'Jira URL',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Project Key',
|
||||
'name' => 'jira-key',
|
||||
'descr' => 'Jira Project Key',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Issue Type',
|
||||
'name' => 'jira-type',
|
||||
'descr' => 'Jira Issue Type',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Jira Username',
|
||||
'name' => 'jira-username',
|
||||
'descr' => 'Jira Username',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Jira Password',
|
||||
'name' => 'jira-password',
|
||||
'descr' => 'Jira Password',
|
||||
'type' => 'text'
|
||||
],
|
||||
],
|
||||
'validation' => [
|
||||
'jira-key' => 'required|string',
|
||||
'jira-url' => 'required|string',
|
||||
'jira-type' => 'required|string',
|
||||
'jira-username' => 'required|string',
|
||||
'jira-password' => 'required|string',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,13 +23,40 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
use LibreNMS\Config;
|
||||
|
||||
class Mail implements Transport
|
||||
class Mail extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
global $config;
|
||||
return send_mail($obj['contacts'], $obj['title'], $obj['msg'], ($config['email_html'] == 'true') ? true : false);
|
||||
return $this->contactMail($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactMail($obj, $opts)
|
||||
{
|
||||
if (empty($this->config['email'])) {
|
||||
$email = $obj['contacts'];
|
||||
} else {
|
||||
$email = $this->config['email'];
|
||||
}
|
||||
return send_mail($email, $obj['title'], $obj['msg'], (Config::get('email_html') == 'true') ? true : false);
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Email',
|
||||
'name' => 'email',
|
||||
'descr' => 'Email address of contact',
|
||||
'type' => 'text',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'email' => 'required|email'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -11,11 +11,20 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Msteams implements Transport
|
||||
class Msteams extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['url'] = $this->config['msteam-url'];
|
||||
}
|
||||
|
||||
return $this->contactMsteams($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactMsteams($obj, $opts)
|
||||
{
|
||||
$url = $opts['url'];
|
||||
$color = ($obj['state'] == 0 ? '#00FF00' : '#FF0000');
|
||||
@@ -40,7 +49,23 @@ class Msteams implements Transport
|
||||
var_dump("Microsoft Teams returned Error, retry later");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Webhook URL',
|
||||
'name' => 'msteam-url',
|
||||
'descr' => 'Microsoft Teams Webhook URL',
|
||||
'type' => 'text',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'msteam-url' => 'required|url'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,25 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Nagios implements Transport
|
||||
class Nagios extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$opts = $this->config['nagios-fifo'];
|
||||
return $this->contactNagios($obj, $opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
return $this->contactNagios($obj, $opts);
|
||||
}
|
||||
|
||||
public static function contactNagios($obj, $opts)
|
||||
{
|
||||
/*
|
||||
host_perfdata_file_template=
|
||||
@@ -55,4 +69,21 @@ class Nagios implements Transport
|
||||
$format .= "\n";
|
||||
return file_put_contents($opts, $format);
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Nagios FIFO',
|
||||
'name' => 'nagios-fifo',
|
||||
'descr' => 'Nagios compatible FIFO',
|
||||
'type' => 'text',
|
||||
],
|
||||
],
|
||||
'validation' => [
|
||||
'nagios-fifo' => 'required',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,19 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Opsgenie implements Transport
|
||||
class Opsgenie extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['url'] = $this->config['genie-url'];
|
||||
}
|
||||
return $this->contactOpsgenie($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactOpsgenie($obj, $opts)
|
||||
{
|
||||
$url = $opts['url'];
|
||||
|
||||
@@ -50,4 +58,21 @@ class Opsgenie implements Transport
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Webhook URL',
|
||||
'name' => 'genie-url',
|
||||
'descr' => 'OpsGenie Webhook URL',
|
||||
'type' => 'text'
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'genie-url' => 'required|url'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -11,11 +11,20 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Osticket implements Transport
|
||||
class Osticket extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['url'] = $this->config['os-url'];
|
||||
$opts['token'] = $this->config['os-token'];
|
||||
}
|
||||
return $this->contactOsticket($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactOsticket($obj, $opts)
|
||||
{
|
||||
global $config;
|
||||
|
||||
@@ -55,4 +64,28 @@ class Osticket implements Transport
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'API URL',
|
||||
'name' => 'os-url',
|
||||
'descr' => 'osTicket API URL',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'API Token',
|
||||
'name' => 'os-token',
|
||||
'descr' => 'osTicket API Token',
|
||||
'type' => 'text'
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'os-url' => 'required|url',
|
||||
'os-token' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,9 +23,9 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Pagerduty implements Transport
|
||||
class Pagerduty extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
@@ -59,4 +59,14 @@ class Pagerduty implements Transport
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function contactPagerduty()
|
||||
{
|
||||
return [];// Pagerduty is a custom transport.
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [];// Pagerduty is a custom transport.
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,29 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Playsms implements Transport
|
||||
class Playsms extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$playsms_opts['url'] = $this->config['playsms-url'];
|
||||
$playsms_opts['user'] = $this->config['playsms-user'];
|
||||
$playsms_opts['token'] = $this->config['playsms-token'];
|
||||
$playsms_opts['from'] = $this->config['playsms-from'];
|
||||
$playsms_opts['to'] = preg_split('/([,\r\n]+)/', $this->config['playsms-mobiles']);
|
||||
return $this->contactDiscord($obj, $playsms_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
return $this->contactPlaysms($obj, $opts);
|
||||
}
|
||||
|
||||
public static function contactPlaysms($obj, $opts)
|
||||
{
|
||||
$data = array("u" => $opts['user'], "h" => $opts['token'], "to" => implode(',', $opts['to']), "msg" => $obj['title']);
|
||||
if (!empty($opts['from'])) {
|
||||
@@ -43,11 +61,52 @@ class Playsms implements Transport
|
||||
$ret = curl_exec($curl);
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
if ($code > 202) {
|
||||
if ($debug) {
|
||||
var_dump($ret);
|
||||
}
|
||||
return false;
|
||||
return var_dump($ret);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'PlaySMS URL',
|
||||
'name' => 'playsms-url',
|
||||
'descr' => 'PlaySMS URL',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'User',
|
||||
'name' => 'playsms-user',
|
||||
'descr' => 'PlaySMS User',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Token',
|
||||
'name' => 'playsms-token',
|
||||
'descr' => 'PlaySMS Token',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'From',
|
||||
'name' => 'playsms-from',
|
||||
'descr' => 'PlaySMS From',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Mobiles',
|
||||
'name' => 'playsms-mobiles',
|
||||
'descr' => 'PlaySMS Mobiles, can be new line or comma separated',
|
||||
'type' => 'textarea',
|
||||
],
|
||||
],
|
||||
'validation' => [
|
||||
'playsms-url' => 'required|url',
|
||||
'playsms-user' => 'required|string',
|
||||
'playsms-token' => 'required|string',
|
||||
'playsms-mobiles' => 'required',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,19 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Pushbullet implements Transport
|
||||
class Pushbullet extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts = $this->config['pushbullet-token'];
|
||||
}
|
||||
return contactPushbullet($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactPushbullet($obj, $opts)
|
||||
{
|
||||
// Note: At this point it might be useful to iterate through $obj['contacts'] and send each of them a note ?
|
||||
|
||||
@@ -55,4 +63,21 @@ class Pushbullet implements Transport
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Access Token',
|
||||
'name' => 'pushbullet-token',
|
||||
'descr' => 'Pushbullet Access Token',
|
||||
'type' => 'text'
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'pushbullet-token' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -37,13 +37,37 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Pushover implements Transport
|
||||
class Pushover extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$pushover_opts = $this->config;
|
||||
unset($pushover_opts['options']);
|
||||
foreach (explode(PHP_EOL, $this->config['options']) as $option) {
|
||||
list($k,$v) = explode('=', $option);
|
||||
$pushover_opts['options'][$k] = $v;
|
||||
}
|
||||
return $this->contactPushover($obj, $pushover_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $api) {
|
||||
$response = $this->contactPushover($obj, $api);
|
||||
if ($response !== true) {
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function contactPushover($obj, $api)
|
||||
{
|
||||
$data = array();
|
||||
$data['token'] = $api['appkey'];
|
||||
$data['user'] = $api['userkey'];
|
||||
@@ -71,9 +95,13 @@ class Pushover implements Transport
|
||||
}
|
||||
$data['title'] = $obj['title'];
|
||||
$data['message'] = $obj['msg'];
|
||||
if ($api['options']) {
|
||||
$data = array_merge($data, $api['options']);
|
||||
}
|
||||
$curl = curl_init();
|
||||
set_curl_proxy($curl);
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://api.pushover.net/1/messages.json');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
$ret = curl_exec($curl);
|
||||
@@ -82,7 +110,36 @@ class Pushover implements Transport
|
||||
var_dump("Pushover returned error"); //FIXME: proper debugging
|
||||
return 'HTTP Status code ' . $code;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Api Key',
|
||||
'name' => 'appkey',
|
||||
'descr' => 'Api Key',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'User Key',
|
||||
'name' => 'userkey',
|
||||
'descr' => 'User Key',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Pushover Options',
|
||||
'name' => 'options',
|
||||
'descr' => 'Pushover options',
|
||||
'type' => 'textarea',
|
||||
],
|
||||
],
|
||||
'validation' => [
|
||||
'appkey' => 'required',
|
||||
'userkey' => 'required',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,14 +23,34 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Rocket implements Transport
|
||||
class Rocket extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$rocket_opts['url'] = $this->config['rocket-url'];
|
||||
foreach (explode(PHP_EOL, $this->config['rocket-options']) as $option) {
|
||||
list($k,$v) = explode('=', $option);
|
||||
$rocket_opts[$k] = $v;
|
||||
}
|
||||
return $this->contactRocket($obj, $rocket_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $tmp_api) {
|
||||
$host = $tmp_api['url'];
|
||||
$this->contactRocket($obj, $tmp_api);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function contactRocket($obj, $api)
|
||||
{
|
||||
$host = $api['url'];
|
||||
$curl = curl_init();
|
||||
$rocket_msg = strip_tags($obj['msg']);
|
||||
$color = ($obj['state'] == 0 ? '#00FF00' : '#FF0000');
|
||||
@@ -43,10 +63,10 @@ class Rocket implements Transport
|
||||
'text' => $rocket_msg,
|
||||
)
|
||||
),
|
||||
'channel' => $tmp_api['channel'],
|
||||
'username' => $tmp_api['username'],
|
||||
'icon_url' => $tmp_api['icon_url'],
|
||||
'icon_emoji' => $tmp_api['icon_emoji'],
|
||||
'channel' => $api['channel'],
|
||||
'username' => $api['username'],
|
||||
'icon_url' => $api['icon_url'],
|
||||
'icon_emoji' => $api['icon_emoji'],
|
||||
);
|
||||
$alert_message = json_encode($data);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
|
||||
@@ -64,7 +84,29 @@ class Rocket implements Transport
|
||||
var_dump("Return: " . $ret); //FIXME: propper debuging
|
||||
return 'HTTP Status code ' . $code;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Webhook URL',
|
||||
'name' => 'rocket-url',
|
||||
'descr' => 'Rocket.chat Webhook URL',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Rocket.chat Options',
|
||||
'name' => 'rocket-options',
|
||||
'descr' => 'Rocket.chat Options',
|
||||
'type' => 'textarea',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'rocket-url' => 'required|url',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,34 +23,59 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Slack implements Transport
|
||||
class Slack extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$slack_opts['url'] = $this->config['slack-url'];
|
||||
foreach (explode(PHP_EOL, $this->config['options']) as $option) {
|
||||
list($k,$v) = explode('=', $option);
|
||||
$slack_opts[$k] = $v;
|
||||
}
|
||||
return $this->contactSlack($obj, $slack_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $tmp_api) {
|
||||
$host = $tmp_api['url'];
|
||||
$this->contactSlack($obj, $tmp_api);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function contactSlack($obj, $api)
|
||||
{
|
||||
$host = $api['url'];
|
||||
$curl = curl_init();
|
||||
$slack_msg = strip_tags($obj['msg']);
|
||||
$color = ($obj['state'] == 0 ? '#00FF00' : '#FF0000');
|
||||
$data = array(
|
||||
'attachments' => array(
|
||||
0 => array(
|
||||
$data = [
|
||||
'attachments' => [
|
||||
0 => [
|
||||
'fallback' => $slack_msg,
|
||||
'color' => $color,
|
||||
'title' => $obj['title'],
|
||||
'text' => $slack_msg,
|
||||
'mrkdwn_in' => array('text', 'fallback')
|
||||
)
|
||||
),
|
||||
'channel' => $tmp_api['channel'],
|
||||
'username' => $tmp_api['username'],
|
||||
'icon_url' => $tmp_api['icon_url'],
|
||||
'icon_emoji' => $tmp_api['icon_emoji'],
|
||||
);
|
||||
'mrkdwn_in' => ['text', 'fallback'],
|
||||
'author_name' => $api['author_name'],
|
||||
'fields' => [
|
||||
[
|
||||
'title' => 'Priority',
|
||||
'value' => ucfirst($obj['severity']),
|
||||
'short' => false,
|
||||
]
|
||||
],
|
||||
],
|
||||
],
|
||||
'channel' => $api['channel'],
|
||||
];
|
||||
$alert_message = json_encode($data);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
set_curl_proxy($curl);
|
||||
curl_setopt($curl, CURLOPT_URL, $host);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
@@ -65,7 +90,29 @@ class Slack implements Transport
|
||||
var_dump("Return: " . $ret); //FIXME: propper debuging
|
||||
return 'HTTP Status code ' . $code;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Webhook URL',
|
||||
'name' => 'slack-url',
|
||||
'descr' => 'Slack Webhook URL',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Slack Options',
|
||||
'name' => 'options',
|
||||
'descr' => 'Slack Options',
|
||||
'type' => 'textarea',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'slack-url' => 'required|url',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,18 +23,35 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Smseagle implements Transport
|
||||
class Smseagle extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
$params = array(
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$smseagle_opts['url'] = $this->config['playsms-url'];
|
||||
$smseagle_opts['user'] = $this->config['playsms-user'];
|
||||
$smseagle_opts['token'] = $this->config['playsms-pass'];
|
||||
$smseagle_opts['to'] = preg_split('/([,\r\n]+)/', $this->config['playsms-mobiles']);
|
||||
return $this->contactSmseagle($obj, $smseagle_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
return $this->contactSmseagle($obj, $opts);
|
||||
}
|
||||
|
||||
public static function contactSmseagle($obj, $opts)
|
||||
{
|
||||
$params = [
|
||||
'login' => $opts['user'],
|
||||
'pass' => $opts['token'],
|
||||
'to' => implode(',', $opts['to']),
|
||||
'message' => $obj['title'],
|
||||
);
|
||||
];
|
||||
$url = 'http://' . $opts['url'] . '/index.php/http_api/send_sms?' . http_build_query($params);
|
||||
$curl = curl_init($url);
|
||||
|
||||
@@ -49,4 +66,42 @@ class Smseagle implements Transport
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'SMSEagle URL',
|
||||
'name' => 'smseagle-url',
|
||||
'descr' => 'SMSEagle URL',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'User',
|
||||
'name' => 'smseagle-user',
|
||||
'descr' => 'SMSEagle User',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Password',
|
||||
'name' => 'smseagle-pass',
|
||||
'descr' => 'SMSEagle Password',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Mobiles',
|
||||
'name' => 'smseagle-mobiles',
|
||||
'descr' => 'SMSEagle Mobiles, can be new line or comma separated',
|
||||
'type' => 'textarea',
|
||||
],
|
||||
],
|
||||
'validation' => [
|
||||
'smseagle-url' => 'required|url',
|
||||
'smseagle-user' => 'required|string',
|
||||
'smseagle-pass' => 'required|string',
|
||||
'smseagle-mobiles' => 'required',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -16,11 +16,21 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Syslog implements Transport
|
||||
class Syslog extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['syslog_host'] = $this->config['syslog-host'];
|
||||
$opts['syslog_port'] = $this->config['syslog-port'];
|
||||
$opts['syslog_facility'] = $this->config['syslog-facility'];
|
||||
}
|
||||
return $this->contactSyslog($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactSyslog($obj, $opts)
|
||||
{
|
||||
$syslog_host = '127.0.0.1';
|
||||
$syslog_port = 514;
|
||||
@@ -116,4 +126,35 @@ class Syslog implements Transport
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Host',
|
||||
'name' => 'syslog-host',
|
||||
'descr' => 'Syslog Host',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Port',
|
||||
'name' => 'syslog-port',
|
||||
'descr' => 'Syslog Port',
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'title' => 'Facility',
|
||||
'name' => 'syslog-facility',
|
||||
'descr' => 'Syslog Facility',
|
||||
'type' => 'text'
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'syslog-host' => 'required|string',
|
||||
'syslog-port' => 'required|numeric',
|
||||
'syslog-facility' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -24,17 +24,33 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Telegram implements Transport
|
||||
class Telegram extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (empty($this->config)) {
|
||||
return $this->deliverAlertOld($obj, $opts);
|
||||
}
|
||||
$telegram_opts['chat_id'] = $this->config['telegram-chat-id'];
|
||||
$telegram_opts['token'] = $this->config['telegram-token'];
|
||||
return $this->contactTelegram($obj, $telegram_opts);
|
||||
}
|
||||
|
||||
public function deliverAlertOld($obj, $opts)
|
||||
{
|
||||
foreach ($opts as $chat_id => $data) {
|
||||
$this->contactTelegram($obj, $data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function contactTelegram($obj, $data)
|
||||
{
|
||||
$curl = curl_init();
|
||||
set_curl_proxy($curl);
|
||||
$text = urlencode($obj['msg']);
|
||||
print_r($data);
|
||||
curl_setopt($curl, CURLOPT_URL, ("https://api.telegram.org/bot{$data['token']}/sendMessage?chat_id={$data['chat_id']}&text=$text"));
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
$ret = curl_exec($curl);
|
||||
@@ -45,7 +61,30 @@ class Telegram implements Transport
|
||||
var_dump("Return: " . $ret); //FIXME: propper debuging
|
||||
return 'HTTP Status code ' . $code;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Chat ID',
|
||||
'name' => 'telegram-chat-id',
|
||||
'descr' => 'Telegram Chat ID',
|
||||
'type' => 'text',
|
||||
],
|
||||
[
|
||||
'title' => 'Token',
|
||||
'name' => 'telegram-token',
|
||||
'descr' => 'Telegram Token',
|
||||
'type' => 'text',
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'telegram-chat-id' => 'required|string',
|
||||
'telegram-token' => 'required|string',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -24,11 +24,19 @@
|
||||
*/
|
||||
namespace LibreNMS\Alert\Transport;
|
||||
|
||||
use LibreNMS\Interfaces\Alert\Transport;
|
||||
use LibreNMS\Alert\Transport;
|
||||
|
||||
class Victorops implements Transport
|
||||
class Victorops extends Transport
|
||||
{
|
||||
public function deliverAlert($obj, $opts)
|
||||
{
|
||||
if (!empty($this->config)) {
|
||||
$opts['url'] = $this->config['victorops-url'];
|
||||
}
|
||||
return $this->contactVictorops($obj, $opts);
|
||||
}
|
||||
|
||||
public function contactVictorops($obj, $opts)
|
||||
{
|
||||
$url = $opts['url'];
|
||||
|
||||
@@ -65,4 +73,21 @@ class Victorops implements Transport
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function configTemplate()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
[
|
||||
'title' => 'Post URL',
|
||||
'name' => 'victorops-url',
|
||||
'descr' => 'Victorops Post URL',
|
||||
'type' => 'text'
|
||||
]
|
||||
],
|
||||
'validation' => [
|
||||
'victorops-url' => 'required|string'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
42
doc/Alerting/Creating-Transport.md
Normal file
42
doc/Alerting/Creating-Transport.md
Normal file
@@ -0,0 +1,42 @@
|
||||
source: Alerting/Creating-Transport.md
|
||||
|
||||
# Creating a new Transport.
|
||||
|
||||
### File location
|
||||
All transports are located in `LibreNMS\Alert\Transport` and the files are named after the Transport name. I.e
|
||||
`Discord.php` for Discord.
|
||||
|
||||
### Transport structure.
|
||||
The following functions are required for a new transport to pass the unit tests:
|
||||
|
||||
`deliverAlert()` - This is function called within alerts to invoke the transport. Here you should do any post processing
|
||||
of the transport config to get it ready for use.
|
||||
|
||||
`contact$Transport()` - This is named after the transport so for Discord it would be `contactDiscord()`. This is what
|
||||
actually interacts with the 3rd party API, invokes the mail command or whatever you want your alert to do.
|
||||
|
||||
`configTemplate()` - This is used to define the form that will accept the transport config in the webui and then what
|
||||
data should be validated and how. Validation is done using [Laravel validation](https://laravel.com/docs/5.4/validation)
|
||||
|
||||
The following function is __not__ required for new Transports and is for legacy reasons only. `deliverAlertOld()`.
|
||||
|
||||
### WebUI
|
||||
At present you will also need to add the new transport to the select part of the form in
|
||||
`html/includes/modal/edit_alert_transport.inc.php`. I.e:
|
||||
|
||||
`<option value="discord-form">Discord</option>`
|
||||
|
||||
Please ensure you add the new entry in the correct location sorted alphabetically.
|
||||
|
||||
### Documentation
|
||||
Please don't forget to update the [Transport](Transports.md) file to include details of your new transport.
|
||||
|
||||
A table should be provided to indicate the form values that we ask for and examples. I.e:
|
||||
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Discord URL | https://discordapp.com/api/webhooks/4515489001665127664/82-sf4385ysuhfn34u2fhfsdePGLrg8K7cP9wl553Fg6OlZuuxJGaa1d54fe
|
||||
Options | username=myname
|
||||
```
|
@@ -2,237 +2,151 @@ source: Alerting/Transports.md
|
||||
|
||||
# Transports
|
||||
|
||||
Transports are located within `LibreNMS/Alert/Transport/` and defined as well as configured via ~~`$config['alert']['transports']['Example'] = 'Some Options'`~~.
|
||||
Transports are located within `LibreNMS/Alert/Transport/` and can be configured within the WebUI under Alerts -> Alert Transports.
|
||||
|
||||
Contacts will be gathered automatically and passed to the configured transports.
|
||||
By default the Contacts will be only gathered when the alert triggers and will ignore future changes in contacts for the incident. If you want contacts to be re-gathered before each dispatch, please set ~~`$config['alert']['fixed-contacts'] = false;`~~ in your config.php.
|
||||
By default the Contacts will be only gathered when the alert triggers and will ignore future changes in contacts for the incident.
|
||||
If you want contacts to be re-gathered before each dispatch, please set 'Updates to contact email addresses not honored' to Off in the WebUI.
|
||||
|
||||
The contacts will always include the `SysContact` defined in the Device's SNMP configuration and also every LibreNMS-User that has at least `read`-permissions on the entity that is to be alerted.
|
||||
The contacts will always include the `SysContact` defined in the Device's SNMP configuration and also every LibreNMS user that has at least `read`-permissions on the entity that is to be alerted.
|
||||
|
||||
At the moment LibreNMS only supports Port or Device permissions.
|
||||
|
||||
You can exclude the `SysContact` by setting:
|
||||
You can exclude the `SysContact` by toggling 'Issue alerts to sysContact'.
|
||||
|
||||
```php
|
||||
$config['alert']['syscontact'] = false;
|
||||
```
|
||||
To include users that have `Global-Read`, `Administrator` or `Normal-User` permissions it is required to toggle the options:
|
||||
|
||||
To include users that have `Global-Read` or `Administrator` permissions it is required to add these additions to the `config.php` respectively:
|
||||
- Issue alerts to admins.
|
||||
- Issue alerts to read only users
|
||||
- Issue alerts to normal users.
|
||||
|
||||
```php
|
||||
$config['alert']['globals'] = true; //Include Global-Read into alert-contacts
|
||||
$config['alert']['admins'] = true; //Include Administrators into alert-contacts
|
||||
```
|
||||
## Using a Proxy?
|
||||
[Proxy Configuration](../Support/Configuration.md#proxy-support)
|
||||
|
||||
## API
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
|
||||
API transports definitions are a bit more complex than the E-Mail configuration.
|
||||
The basis for configuration is ~~`$config['alert']['transports']['api'][METHOD]`~~ where `METHOD` can be `get`,`post` or `put`.
|
||||
This basis has to contain an array with URLs of each API to call.
|
||||
|
||||
The URL can have the same placeholders as defined in the [Template-Syntax](Templates#syntax).
|
||||
If the `METHOD` is `get`, all placeholders will be URL-Encoded.
|
||||
The API transport uses cURL to call the APIs, therefore you might need to install `php5-curl` or similar in order to make it work.
|
||||
__Note__: it is highly recommended to define own [Templates](Templates) when you want to use the API transport. The default template might exceed URL-length for GET requests and therefore cause all sorts of errors.
|
||||
|
||||
Example:
|
||||
If the `Api Method` is `get`, all placeholders will be URL-Encoded.
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['api']['get'][] = "https://api.thirdparti.es/issue?apikey=abcdefg&subject=%title";
|
||||
```
|
||||
The API transport uses cURL to call the APIs, therefore you might need to install `php curl` to make it work.
|
||||
|
||||
__Note__: it is highly recommended to define your own [Templates](Templates) when you want to use the API transport. The default template might exceed URL-length for GET requests and therefore cause all sorts of errors.
|
||||
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
API Method | get
|
||||
API URL | http://my.example.com/api
|
||||
|
||||
## Boxcar
|
||||
Copy your access token from the Boxcar app or from the Boxcar.io website and setup the transport.
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
[Boxcar Docs](http://developer.boxcar.io/api/publisher/)
|
||||
|
||||
Enabling Boxcar support is super easy.
|
||||
Copy your access token from the Boxcar app or from the Boxcar.io website and setup the transport in your config.php like:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['boxcar'][] = array(
|
||||
"access_token" => 'ACCESSTOKENGOESHERE',
|
||||
);
|
||||
```
|
||||
|
||||
To modify the Critical alert sound, add the 'sound_critical' parameter, example:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['boxcar'][] = array(
|
||||
"access_token" => 'ACCESSTOKENGOESHERE',
|
||||
"sound_critical" => 'detonator-charge',
|
||||
);
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Access Token | i23f23mr23rwerw
|
||||
|
||||
## Canopsis
|
||||
Canopsis is a hypervision tool. LibreNMS can send alerts to Canopsis which are then converted to canopsis events.
|
||||
|
||||
Canopsis is a hypervision tool. LibreNMS can send alerts to Canopsis which are then converted to canopsis events. To configure the transport, go to:
|
||||
[Canopsis Docs](http://www.canopsis.org/wp-content/themes/canopsis/doc/sakura/user-guide/event-spec.html)
|
||||
|
||||
Global Settings -> Alerting Settings -> Canopsis Transport.
|
||||
|
||||
You will need to fill this paramaters :
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['canopsis']['host'] = 'www.xxx.yyy.zzz';
|
||||
$config['alert']['transports']['canopsis']['port'] = '5672';
|
||||
$config['alert']['transports']['canopsis']['user'] = 'admin';
|
||||
$config['alert']['transports']['canopsis']['passwd'] = 'my_password';
|
||||
$config['alert']['transports']['canopsis']['vhost'] = 'canopsis';
|
||||
```
|
||||
|
||||
For more information about canopsis and its events, take a look here :
|
||||
http://www.canopsis.org/
|
||||
http://www.canopsis.org/wp-content/themes/canopsis/doc/sakura/user-guide/event-spec.html
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Hostname | www.xxx.yyy.zzz
|
||||
Port Number | 5672
|
||||
User | admin
|
||||
Password | my_password
|
||||
Vhost | canopsis
|
||||
|
||||
## Cisco Spark
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
|
||||
Cisco Spark. LibreNMS can send alerts to a Cisco Spark room. To make this possible you need to have a RoomID and a token.
|
||||
|
||||
For more information about Cisco Spark RoomID and token, take a look here :
|
||||
https://developer.ciscospark.com/getting-started.html
|
||||
https://developer.ciscospark.com/resource-rooms.html
|
||||
|
||||
To configure the transport, go to:
|
||||
- [Getting started](https://developer.ciscospark.com/getting-started.html)
|
||||
- [Rooms](https://developer.ciscospark.com/resource-rooms.html)
|
||||
|
||||
Global Settings -> Alerting Settings -> Cisco Spark transport.
|
||||
|
||||
This can also be done manually in config.php :
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['ciscospark']['token'] = '1234567890QWERTYUIOP';
|
||||
$config['alert']['transports']['ciscospark']['roomid'] = '1234567890QWERTYUIOP';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
API Token | ASd23r23edewda
|
||||
RoomID | 34243243251
|
||||
|
||||
## Clickatell
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
Clickatell provides a REST-API requiring an Authorization-Token and at least one Cellphone number.
|
||||
Please consult Clickatell's documentation regarding number formatting.
|
||||
|
||||
[Clickatell Docs](https://www.clickatell.com/developers/api-documentation/rest-api-request-parameters/)
|
||||
|
||||
Here an example using 3 numbers, any amount of numbers is supported:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['clickatell']['token'] = 'MYFANCYACCESSTOKEN';
|
||||
$config['alert']['transports']['clickatell']['to'][] = '+1234567890';
|
||||
$config['alert']['transports']['clickatell']['to'][] = '+1234567891';
|
||||
$config['alert']['transports']['clickatell']['to'][] = '+1234567892';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Token | dsaWd3rewdwea
|
||||
Mobile Numbers | +1234567890,+1234567891,+1234567892
|
||||
|
||||
## Discord
|
||||
The Discord transport will POST the alert message to your Discord Incoming WebHook. Simple html tags are stripped from
|
||||
the message.
|
||||
|
||||
The Discord transport will POST the alert message to your Discord Incoming WebHook (https://discordapp.com/developers/docs/resources/webhook). Simple html tags are stripped from the message. The only required value is for url, without this no call to Discord will be made. Below is an example webhook url:
|
||||
The only required value is for url, without this no call to Discord will be made. The Options field supports the
|
||||
JSON/Form Params listed in the Discord Docs below.
|
||||
|
||||
```
|
||||
https://discordapp.com/api/webhooks/4515489001665127664/82-sf4385ysuhfn34u2fhfsdePGLrg8K7cP9wl553Fg6OlZuuxJGaa1d54fe
|
||||
```
|
||||
[Discord Docs](https://discordapp.com/developers/docs/resources/webhook#execute-webhook)
|
||||
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Discord URL | https://discordapp.com/api/webhooks/4515489001665127664/82-sf4385ysuhfn34u2fhfsdePGLrg8K7cP9wl553Fg6OlZuuxJGaa1d54fe
|
||||
Options | username=myname
|
||||
|
||||
## Elasticsearch
|
||||
You can have LibreNMS send alerts to an elasticsearch database. Each fault will be sent as a separate document.
|
||||
|
||||
You can have LibreNMS emit alerts to an elasticsearch database. Each fault will be sent as a separate document.
|
||||
The index pattern uses strftime() formatting.
|
||||
The proxy setting uses the proxy set in config.php if true and does not if false; this allows you to use local servers.
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['elasticsearch']['es_host'] = '127.0.0.1';
|
||||
$config['alert']['transports']['elasticsearch']['es_port'] = 9200;
|
||||
$config['alert']['transports']['elasticsearch']['es_index'] = 'librenms-%Y.%m.%d';
|
||||
$config['alert']['transports']['elasticsearch']['es_proxy'] = false;
|
||||
```
|
||||
|
||||
## E-Mail
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
|
||||
For all but the default contact, we support setting multiple email addresses separated by a comma. So you can
|
||||
set the devices sysContact, override the sysContact or have your users emails set like:
|
||||
|
||||
`email@domain.com, alerting@domain.com`
|
||||
|
||||
E-Mail transport is enabled with adding the following to your `config.php`:
|
||||
```php
|
||||
$config['alert']['transports']['mail'] = true;
|
||||
```
|
||||
|
||||
The E-Mail transports uses the same email-configuration like the rest of LibreNMS.
|
||||
As a small reminder, here is it's configuration directives including defaults:
|
||||
|
||||
```php
|
||||
$config['email_backend'] = 'mail'; // Mail backend. Allowed: "mail" (PHP's built-in), "sendmail", "smtp".
|
||||
$config['email_from'] = NULL; // Mail from. Default: "ProjectName" <projectid@`hostname`>
|
||||
$config['email_user'] = $config['project_id'];
|
||||
$config['email_sendmail_path'] = '/usr/sbin/sendmail'; // The location of the sendmail program.
|
||||
$config['email_html'] = FALSE; // Whether to send HTML email as opposed to plaintext
|
||||
$config['email_smtp_host'] = 'localhost'; // Outgoing SMTP server name.
|
||||
$config['email_smtp_port'] = 25; // The port to connect.
|
||||
$config['email_smtp_timeout'] = 10; // SMTP connection timeout in seconds.
|
||||
$config['email_smtp_secure'] = NULL; // Enable encryption. Use 'tls' or 'ssl'
|
||||
$config['email_smtp_auth'] = FALSE; // Whether or not to use SMTP authentication.
|
||||
$config['email_smtp_username'] = NULL; // SMTP username.
|
||||
$config['email_smtp_password'] = NULL; // Password for SMTP authentication.
|
||||
|
||||
$config['alert']['default_only'] = false; //Only issue to default_mail
|
||||
$config['alert']['default_mail'] = ''; //Default email
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Host | 127.0.0.1
|
||||
Port | 9200
|
||||
Index Patter | librenms-%Y.%m.%d
|
||||
|
||||
## Gitlab
|
||||
LibreNMS will create issues for warning and critical level alerts however only title and description are set.
|
||||
Uses Personal access tokens to authenticate with Gitlab and will store the token in cleartext.
|
||||
|
||||
LibreNMS will create issues for warning and critical level alerts however only title and description are set. Uses Personal access tokens to authenticate with Gitlab and will store the token in cleartext.
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['gitlab']['host'] = 'http://gitlab.host.tld';
|
||||
$config['alert']['transports']['gitlab']['project_id'] = '1';
|
||||
$config['alert']['transports']['gitlab']['key'] = 'AbCdEf12345';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Host | http://gitlab.host.tld
|
||||
Project ID | 1
|
||||
Personal Access Token | AbCdEf12345
|
||||
|
||||
## HipChat
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
The HipChat transport requires the following:
|
||||
|
||||
__room_id__ = HipChat Room ID
|
||||
|
||||
__url__ = HipChat API URL+API Key
|
||||
|
||||
__from__ = The name that will be displayed
|
||||
|
||||
The HipChat transport makes the following optional:
|
||||
|
||||
__color__ = Any of HipChat's supported message colors
|
||||
|
||||
__message_format__ = Any of HipChat's supported message formats
|
||||
|
||||
__notify__ = 0 or 1
|
||||
|
||||
See the HipChat API Documentation for
|
||||
[rooms/message](https://www.hipchat.com/docs/api/method/rooms/message)
|
||||
See the HipChat API Documentation for [rooms/message](https://www.hipchat.com/docs/api/method/rooms/message)
|
||||
for details on acceptable values.
|
||||
|
||||
> You may notice that the link points at the "deprecated" v1 API. This is
|
||||
> because the v2 API is still in beta.
|
||||
|
||||
Below are two examples of sending messages to a HipChat room.
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
API URL | https://api.hipchat.com/v1/rooms/message?auth_token=109jawregoaihj
|
||||
Room ID | 7654321
|
||||
From Name | LibreNMS
|
||||
Options | color = red
|
||||
| notify = 1
|
||||
| message_format = text
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['hipchat'][] = array("url" => "https://api.hipchat.com/v1/rooms/message?auth_token=9109jawregoaih",
|
||||
"room_id" => "1234567",
|
||||
"from" => "LibreNMS");
|
||||
|
||||
$config['alert']['transports']['hipchat'][] = array("url" => "https://api.hipchat.com/v1/rooms/message?auth_token=109jawregoaihj",
|
||||
"room_id" => "7654321",
|
||||
"from" => "LibreNMS",
|
||||
"color" => "red",
|
||||
"notify" => 1,
|
||||
"message_format" => "text");
|
||||
```
|
||||
|
||||
These settings can also be configured from the WebUI, here's an example used for the HipChat V2 API:
|
||||

|
||||
At present the following options are supported: `color`, `notify` and `message_format`.
|
||||
|
||||
> Note: The default message format for HipChat messages is HTML. It is
|
||||
> recommended that you specify the `text` message format to prevent unexpected
|
||||
@@ -240,102 +154,95 @@ These settings can also be configured from the WebUI, here's an example used for
|
||||
> `>`).
|
||||
|
||||
## IRC
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
|
||||
The IRC transports only works together with the LibreNMS IRC-Bot.
|
||||
Configuration of the LibreNMS IRC-Bot is described [here](https://github.com/librenms/librenms/blob/master/doc/Extensions/IRC-Bot.md).
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['irc'] = true;
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
IRC | enabled
|
||||
|
||||
## JIRA
|
||||
You can have LibreNMS create issues on a Jira instance for critical and warning alerts. The Jira transport only sets
|
||||
summary and description fields. Therefore your Jira project must not have any other mandatory field for the provided
|
||||
issuetype. The config fields that need to set are Jira URL, Jira username, Jira password, Project key, and issue type.
|
||||
Currently http authentication is used to access Jira and Jira username and password will be stored as cleartext in the
|
||||
LibreNMS database.
|
||||
|
||||
You can have LibreNMS create issues on a Jira instance for critical and warning alerts. The Jira transport only sets summary and description fiels. Therefore your Jira project must not have any other mandatory field for the provided issuetype. The config fields that need to set are Jira URL, Jira username, Jira password, Project key, and issue type.
|
||||
Currently http authentication is used to access Jira and Jira username and password will be stored as cleartext in the LibreNMS database.
|
||||
[Jira Issue Types](https://confluence.atlassian.com/adminjiracloud/issue-types-844500742.html)
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['jira']['url'] = 'https://myjira.mysite.com';
|
||||
$config['alert']['transports']['jira']['username'] = 'myjirauser';
|
||||
$config['alert']['transports']['jira']['password'] = 'myjirapass';
|
||||
$config['alert']['transports']['jira']['prjkey'][] = 'JIRAPROJECTKEY';
|
||||
$config['alert']['transports']['jira']['issuetype'][] = 'Myissuetype';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
URL | https://myjira.mysite.com
|
||||
Project Key | JIRAPROJECTKEY
|
||||
Issue Type | Myissuetype
|
||||
Jira Username | myjirauser
|
||||
Jira Password | myjirapass
|
||||
|
||||
## Mail
|
||||
For all but the default contact, we support setting multiple email addresses separated by a comma. So you can
|
||||
set the devices sysContact, override the sysContact or have your users emails set like:
|
||||
|
||||
`email@domain.com, alerting@domain.com`
|
||||
|
||||
The E-Mail transports uses the same email-configuration like the rest of LibreNMS.
|
||||
As a small reminder, here is it's configuration directives including defaults:
|
||||
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Email | me@example.com
|
||||
|
||||
## Microsoft Teams
|
||||
Microsoft Teams. LibreNMS can send alerts to Microsoft Teams Connector API which are then posted to a specific channel.
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
Microsoft Teams. LibreNMS can send alerts to Microsoft Teams Connector API which are then posted to a specific channel. To configure the transport, go to:
|
||||
|
||||
Global Settings -> Alerting Settings -> Microsoft Teams Transport.
|
||||
|
||||
This can also be done manually in config.php :
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['msteams']['url'] = 'https://outlook.office365.com/webhook/123456789';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
WebHook URL | https://outlook.office365.com/webhook/123456789
|
||||
|
||||
## Nagios Compatible
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
|
||||
The nagios transport will feed a FIFO at the defined location with the same format that nagios would.
|
||||
This allows you to use other Alerting-Systems to work with LibreNMS, for example [Flapjack](http://flapjack.io).
|
||||
```php
|
||||
$config['alert']['transports']['nagios'] = "/path/to/my.fifo"; //Flapjack expects it to be at '/var/cache/nagios3/event_stream.fifo'
|
||||
```
|
||||
This allows you to use other alerting systems with LibreNMS, for example [Flapjack](http://flapjack.io).
|
||||
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Nagios FIFO | /path/to/my.fifo
|
||||
|
||||
## OpsGenie
|
||||
Using OpsGenie LibreNMS integration, LibreNMS forwards alerts to OpsGenie with detailed information.
|
||||
OpsGenie acts as a dispatcher for LibreNMS alerts, determines the right people to notify based on on-call
|
||||
schedules and notifies via email, text messages (SMS), phone calls and iOS & Android push notifications.
|
||||
Then escalates alerts until the alert is acknowledged or closed.
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
Create a [LibreNMS Integration](https://docs.opsgenie.com/docs/librenms-integration) from the integrations page
|
||||
once you signup. Then copy the API key from OpsGenie to LibreNMS.
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
If you want to automatically ack and close alerts, leverage Marid integration. More detail with screenshots is
|
||||
available in [OpsGenie LibreNMS Integration page](https://docs.opsgenie.com/docs/librenms-integration).
|
||||
|
||||
Using OpsGenie LibreNMS integration, LibreNMS forwards alerts to OpsGenie with detailed information. OpsGenie acts as a dispatcher for LibreNMS alerts, determines the right people to notify based on on-call schedules– notifies via email, text messages (SMS), phone calls and iOS & Android push notifications, and escalates alerts until the alert is acknowledged or closed.
|
||||
|
||||
Create a [LibreNMS Integration](https://docs.opsgenie.com/docs/librenms-integration) from the integrations page once you signup. Then, copy the API key from OpsGenie to LibreNMS.
|
||||
|
||||
If you want to automatically ack and close alerts, leverage Marid integration. More detail with screenshots is available in [OpsGenie LibreNMS Integration page](https://docs.opsgenie.com/docs/librenms-integration).
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
WebHook URL | https://url/path/to/webhook
|
||||
|
||||
## osTicket
|
||||
LibreNMS can send alerts to osTicket API which are then converted to osTicket tickets.
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
osTicket, open source ticket system. LibreNMS can send alerts to osTicket API which are then converted to osTicket tickets. To configure the transport, go to:
|
||||
|
||||
Global Settings -> Alerting Settings -> osTicket Transport.
|
||||
|
||||
This can also be done manually in config.php :
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['osticket']['url'] = 'http://osticket.example.com/api/http.php/tickets.json';
|
||||
$config['alert']['transports']['osticket']['token'] = '123456789';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
API URL | http://osticket.example.com/api/http.php/tickets.json
|
||||
API Token | 123456789
|
||||
|
||||
## PagerDuty
|
||||
PagerDuty setup is currently done by a two way integration. Start this process from Settings -> Alerting Settings from within LibreNMS.
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
Enabling PagerDuty transports is almost as easy as enabling email-transports.
|
||||
|
||||
All you need is to create a Service with type Generic API on your PagerDuty dashboard.
|
||||
|
||||
Now copy your API-Key from the newly created Service and setup the transport like:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['pagerduty'] = 'MYAPIKEYGOESHERE';
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
__Note__: Currently ACK notifications are not transported to PagerDuty, This is going to be fixed within the next major version (version by date of writing: 2015.05)
|
||||
[PagerDuty Docs](https://www.pagerduty.com/docs/guides/librenms-integration-guide/)
|
||||
|
||||
## Philips Hue
|
||||
|
||||
Want to spice up your noc life? LibreNMS will flash all lights connected to your philips hue bridge whenever an alert is triggered.
|
||||
|
||||
To setup, go to the you http://`your-bridge-ip`/debug/clip.html
|
||||
@@ -346,137 +253,127 @@ To setup, go to the you http://`your-bridge-ip`/debug/clip.html
|
||||
- Click on `POST`
|
||||
- In the `Command Response` You should see output with your username. Copy this without the quotes
|
||||
|
||||
|
||||
More Info: [Philips Hue Documentation](https://www.developers.meethue.com/documentation/getting-started)
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['hue']['bridge'] = 'http://bridge.example.com';
|
||||
$config['alert']['transports']['hue']['user'] = 'af89jauaf98aj34r';
|
||||
$config['alert']['transports']['hue']['duration'] = 'lselect';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Host | http://your-bridge-ip
|
||||
Hue User | username
|
||||
Duration | 1 Second
|
||||
|
||||
## PlaySMS
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
PlaySMS is an open source SMS-Gateway that can be used via their HTTP-API using a Username and WebService-Token.
|
||||
PlaySMS is an open source SMS-Gateway that can be used via their HTTP API using a Username and WebService Token.
|
||||
Please consult PlaySMS's documentation regarding number formatting.
|
||||
|
||||
[PlaySMS Docs](https://github.com/antonraharja/playSMS/blob/master/documents/development/WEBSERVICES.md)
|
||||
|
||||
Here an example using 3 numbers, any amount of numbers is supported:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['playsms']['url'] = 'https://localhost/index.php?app=ws';
|
||||
$config['alert']['transports']['playsms']['user'] = 'user1';
|
||||
$config['alert']['transports']['playsms']['token'] = 'MYFANCYACCESSTOKEN';
|
||||
$config['alert']['transports']['playsms']['from'] = '+1234567892'; //Optional
|
||||
$config['alert']['transports']['playsms']['to'][] = '+1234567890';
|
||||
$config['alert']['transports']['playsms']['to'][] = '+1234567891';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
PlaySMS | https://localhost/index.php?app=ws
|
||||
User | user1
|
||||
Token | MYFANCYACCESSTOKEN
|
||||
From | My Name
|
||||
Mobiles | +1234567892,+1234567890,+1234567891
|
||||
|
||||
## Pushbullet
|
||||
Get your Access Token from your Pushbullet's settings page and set it in your transport:
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
Enabling Pushbullet is a piece of cake.
|
||||
Get your Access Token from your Pushbullet's settings page and set it in your config like:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['pushbullet'] = 'MYFANCYACCESSTOKEN';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Access Token | MYFANCYACCESSTOKEN
|
||||
|
||||
## Pushover
|
||||
If you want to change the [notification sounds](https://pushover.net/api#sounds) then add it in Pushover Options:
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
|
||||
If you want to change the [notification sounds](https://pushover.net/api#sounds) then add it in config options as:
|
||||
|
||||
```php
|
||||
sound_critical=falling
|
||||
```
|
||||
`sound_critical=falling`
|
||||
|
||||
Enabling Pushover support is fairly easy, there are only two required parameters.
|
||||
|
||||
Firstly you need to create a new Application (called LibreNMS, for example) in your account on the Pushover website (https://pushover.net/apps)
|
||||
|
||||
Now copy your API Token/Key from the newly created Application and setup the transport in your config.php like:
|
||||
Now copy your API Key and obtain your User Key from the newly created Application and setup the transport.
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['pushover'][] = array(
|
||||
"appkey" => 'APPLICATIONAPIKEYGOESHERE',
|
||||
"userkey" => 'USERKEYGOESHERE',
|
||||
);
|
||||
```
|
||||
[Pushover Docs](https://pushover.net/api)
|
||||
|
||||
To modify the Critical alert sound, add the 'sound_critical' parameter, example:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['pushover'][] = array(
|
||||
"appkey" => 'APPLICATIONAPIKEYGOESHERE',
|
||||
"userkey" => 'USERKEYGOESHERE',
|
||||
"sound_critical" => 'siren',
|
||||
);
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Api Key | APPLICATIONAPIKEYGOESHERE
|
||||
User Key | USERKEYGOESHERE
|
||||
Pushover Options | sound_critical=falling
|
||||
|
||||
## Rocket.chat
|
||||
The Rocket.chat transport will POST the alert message to your Rocket.chat Incoming WebHook using the
|
||||
attachments option. Simple html tags are stripped from the message. All options are optional, the only
|
||||
required value is for url, without this then no call to Rocket.chat will be made.
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
[Rocket.chat Docs](https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage)
|
||||
|
||||
The Rocket.chat transport will POST the alert message to your Rocket.chat Incoming WebHook using the [attachments](https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage) option, you are able to specify multiple webhooks along with the relevant options to go with it. Simple html tags are stripped from the message. All options are optional, the only required value is for url, without this then no call to Rocket.chat will be made. Below is an example of how to send alerts to two channels with different customised options:
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['rocket'][] = array('url' => "https://rocket.url/api/v1/chat.postMessage", 'channel' => '#Alerting');
|
||||
|
||||
$config['alert']['transports']['rocket'][] = array('url' => "https://rocket.url/api/v1/chat.postMessage", 'channel' => '@john', 'username' => 'LibreNMS', 'icon_emoji' => ':ghost:');
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Webhook URL | https://rocket.url/api/v1/chat.postMessage
|
||||
Rocket.chat Options | channel=#Alerting
|
||||
| username=myname
|
||||
| icon_url=http://someurl/image.gif
|
||||
| icon_emoji=:smirk:
|
||||
|
||||
## Slack
|
||||
The Slack transport will POST the alert message to your Slack Incoming WebHook using the attachments option,
|
||||
you are able to specify multiple webhooks along with the relevant options to go with it. Simple html tags
|
||||
are stripped from the message. All options are optional, the only required value is for url, without this
|
||||
then no call to Slack will be made.
|
||||
|
||||
> You can configure these options within the WebUI now, please avoid setting these options within config.php
|
||||
We currently support the following attachment options:
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
`author_name`
|
||||
|
||||
The Slack transport will POST the alert message to your Slack Incoming WebHook using the [attachments](https://api.slack.com/docs/message-attachments) option, you are able to specify multiple webhooks along with the relevant options to go with it. Simple html tags are stripped from the message. All options are optional, the only required value is for url, without this then no call to Slack will be made. Below is an example of how to send alerts to two channels with different customised options:
|
||||
[Slack docs](https://api.slack.com/docs/message-attachments)
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['slack'][] = array('url' => "https://hooks.slack.com/services/A12B34CDE/F56GH78JK/L901LmNopqrSTUVw2w3XYZAB4C", 'channel' => '#Alerting');
|
||||
|
||||
$config['alert']['transports']['slack'][] = array('url' => "https://hooks.slack.com/services/A12B34CDE/F56GH78JK/L901LmNopqrSTUVw2w3XYZAB4C", 'channel' => '@john', 'username' => 'LibreNMS', 'icon_emoji' => ':ghost:');
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Webhook URL | https://slack.com/url/somehook
|
||||
Slack Options | author_name=Me
|
||||
|
||||
## SMSEagle
|
||||
SMSEagle is a hardware SMS Gateway that can be used via their HTTP API using a Username and password.
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
SMSEagle is a hardware SMS Gateway that can be used via their HTTP-API using a Username and password
|
||||
Please consult their documentation at [www.smseagle.eu](http://www.smseagle.eu)
|
||||
Destination numbers are one per line, with no spaces. They can be in either local or international dialling format.
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['smseagle']['url'] = 'ip.add.re.ss';
|
||||
$config['alert']['transports']['smseagle']['user'] = 'smseagle_user';
|
||||
$config['alert']['transports']['smseagle']['token'] = 'smseagle_user_password';
|
||||
$config['alert']['transports']['smseagle']['to'][] = '+3534567890';
|
||||
$config['alert']['transports']['smseagle']['to'][] = '0834567891';
|
||||
```
|
||||
[SMSEagle Docs](http://www.smseagle.eu)
|
||||
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
SMSEagle URL | ip.add.re.ss
|
||||
User | smseagle_user
|
||||
Password | smseagle_user_password
|
||||
Mobiles | +3534567890
|
||||
| 0834567891
|
||||
|
||||
## Syslog
|
||||
|
||||
You can have LibreNMS emit alerts as syslogs complying with RFC 3164.
|
||||
|
||||
More information on RFC 3164 can be found here: https://tools.ietf.org/html/rfc3164
|
||||
|
||||
Example output: `<26> Mar 22 00:59:03 librenms.host.net librenms[233]: [Critical] network.device.net: Port Down - port_id => 98939; ifDescr => xe-1/1/0;`
|
||||
|
||||
Each fault will be sent as a separate syslog.
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['syslog']['syslog_host'] = '127.0.0.1';
|
||||
$config['alert']['transports']['syslog']['syslog_port'] = 514;
|
||||
$config['alert']['transports']['syslog']['syslog_facility'] = 3;
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Host | 127.0.0.1
|
||||
Port | 514
|
||||
Facility | 3
|
||||
|
||||
## Telegram
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
> Thank you to [snis](https://github.com/snis) for these instructions.
|
||||
|
||||
1. First you must create a telegram account and add BotFather to you list. To do this click on the following url: https://telegram.me/botfather
|
||||
@@ -485,7 +382,8 @@ $config['alert']['transports']['syslog']['syslog_facility'] = 3;
|
||||
|
||||
3. Add your bot to telegram with the following url: `http://telegram.me/<botname>` and send some text to the bot.
|
||||
|
||||
4. Now copy your token code and go to the following page in chrome: `https://api.telegram.org/bot<tokencode>/getUpdates`
|
||||
4. The BotFather should have responded with a token, copy your token code and go to the following page in chrome: `https://api.telegram.org/bot<tokencode>/getUpdates`
|
||||
(this could take a while so continue to refresh until you see something similar to below)
|
||||
|
||||
5. You see a json code with the message you sent to the bot. Copy the Chat id. In this example that is “-9787468”
|
||||
`"message":{"message_id":7,"from":"id":656556,"first_name":"Joo","last_name":"Doo","username":"JohnDoo"},"chat":{"id":-9787468,"title":"Telegram Group"},"date":1435216924,"text":"Hi"}}]}`
|
||||
@@ -493,19 +391,26 @@ $config['alert']['transports']['syslog']['syslog_facility'] = 3;
|
||||
6. Now create a new "Telegram transport" in LibreNMS (Global Settings -> Alerting Settings -> Telegram transport).
|
||||
Click on 'Add Telegram config' and put your chat id and token into the relevant box.
|
||||
|
||||
[Telegram Docs](https://core.telegram.org/api)
|
||||
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Chat ID | 34243432
|
||||
Token | 3ed32wwf235234
|
||||
|
||||
## VictorOps
|
||||
|
||||
[Using a proxy?](../Support/Configuration.md#proxy-support)
|
||||
|
||||
VictorOps provide a webHook url to make integration extremely simple. To get the URL required login to your VictorOps account and go to:
|
||||
VictorOps provide a webHook url to make integration extremely simple. To get the URL required login to your VictorOps
|
||||
account and go to:
|
||||
|
||||
Settings -> Integrations -> REST Endpoint -> Enable Integration.
|
||||
|
||||
The URL provided will have $routing_key at the end, you need to change this to something that is unique to the system sending the alerts such as librenms. I.e:
|
||||
The URL provided will have $routing_key at the end, you need to change this to something that is unique to the system
|
||||
sending the alerts such as librenms. I.e:
|
||||
|
||||
`https://alert.victorops.com/integrations/generic/20132414/alert/2f974ce1-08fc-4dg8-a4f4-9aee6cf35c98/librenms`
|
||||
|
||||
```php
|
||||
$config['alert']['transports']['victorops']['url'] = 'https://alert.victorops.com/integrations/generic/20132414/alert/2f974ce1-08fc-4dg8-a4f4-9aee6cf35c98/librenms';
|
||||
```
|
||||
**Example:**
|
||||
Config | Example
|
||||
------ | -------
|
||||
Post URL | https://alert.victorops.com/integrations/generic/20132414/alert/2f974ce1-08fc-4dg8-a4f4-9aee6cf35c98/librenms
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
@@ -148,9 +148,60 @@ if (is_numeric($rule_id) && $rule_id > 0) {
|
||||
|
||||
dbSyncRelationship('alert_device_map', 'rule_id', $rule_id, 'device_id', $devices);
|
||||
dbSyncRelationship('alert_group_map', 'rule_id', $rule_id, 'group_id', $groups);
|
||||
|
||||
//Update transport groups and transports - can't use dbSyncRelationship
|
||||
$transports = [];
|
||||
$groups = [];
|
||||
foreach ((array)$vars['transports'] as $item) {
|
||||
if (starts_with($item, 'g')) {
|
||||
$groups[] = (int)substr($item, 1);
|
||||
} else {
|
||||
$transports[] = (int)$item;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch transport/group mappings already in db
|
||||
$sql = "SELECT `transport_or_group_id` FROM `alert_transport_map` WHERE `target_type`='single' AND `rule_id`=?";
|
||||
$db_transports = dbFetchColumn($sql, [$rule_id]);
|
||||
$sql = "SELECT `transport_or_group_id` FROM `alert_transport_map` WHERE `target_type`='group' AND `rule_id`=?";
|
||||
$db_groups = dbFetchColumn($sql, [$rule_id]);
|
||||
|
||||
// Compare arrays to get add and removed transports/groups
|
||||
$t_add = array_diff($transports, $db_transports);
|
||||
$t_del = array_diff($db_transports, $transports);
|
||||
$g_add = array_diff($groups, $db_groups);
|
||||
$g_del = array_diff($db_groups, $groups);
|
||||
|
||||
// Insert any new mappings
|
||||
$insert = [];
|
||||
foreach ($t_add as $transport_id) {
|
||||
$insert[] = array (
|
||||
'transport_or_group_id' => $transport_id,
|
||||
'target_type' => 'single',
|
||||
'rule_id' => $rule_id
|
||||
);
|
||||
}
|
||||
foreach ($g_add as $group_id) {
|
||||
$insert[] = array(
|
||||
'transport_or_group_id' => $group_id,
|
||||
'target_type' => 'group',
|
||||
'rule_id' => $rule_id
|
||||
);
|
||||
}
|
||||
if (!empty($insert)) {
|
||||
$res = dbBulkInsert($insert, 'alert_transport_map');
|
||||
}
|
||||
|
||||
// Remove old mappings
|
||||
if (!empty($t_del)) {
|
||||
dbDelete('alert_transport_map', 'target_type="single" AND transport_or_group_id IN (?)', array(array(implode(',', $t_del))));
|
||||
}
|
||||
if (!empty($g_del)) {
|
||||
dbDelete('alert_transport_map', 'target_type="group" AND transport_or_group_id IN (?)', array(array(implode(',', $g_del))));
|
||||
}
|
||||
}
|
||||
|
||||
die(json_encode([
|
||||
'status' => $status,
|
||||
'message' => $message,
|
||||
'message' => $message
|
||||
]));
|
||||
|
137
html/includes/forms/alert-transports.inc.php
Normal file
137
html/includes/forms/alert-transports.inc.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* alert-transports.inc.php
|
||||
*
|
||||
* LibreNMS alert-transports.inc.php for processor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2018 Vivia Nguyen-Tran
|
||||
* @author Vivia Nguyen-Tran <vivia@ualberta.ca>
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Translation\FileLoader;
|
||||
use Illuminate\Translation\Translator;
|
||||
use Illuminate\Validation\DatabasePresenceVerifier;
|
||||
use Illuminate\Validation\Factory;
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'You need to be admin'
|
||||
]));
|
||||
}
|
||||
|
||||
$status = 'ok';
|
||||
$message = '';
|
||||
|
||||
$transport_id = $vars['transport_id'];
|
||||
$name = $vars['name'];
|
||||
$is_default = isset($vars['is_default']) ? $vars['is_default'] : null;
|
||||
$transport_type = $vars['transport-type'];
|
||||
|
||||
if ($is_default == 'on') {
|
||||
$is_default = true;
|
||||
} else {
|
||||
$is_default = false;
|
||||
}
|
||||
|
||||
if (empty($name)) {
|
||||
$status = 'error';
|
||||
$message = 'No transport name provided';
|
||||
} elseif (empty($transport_type)) {
|
||||
$status = 'error';
|
||||
$message = 'Missing transport information';
|
||||
} else {
|
||||
$details = array(
|
||||
'transport_name' => $name,
|
||||
'is_default' => $is_default
|
||||
);
|
||||
|
||||
if (is_numeric($transport_id) && $transport_id > 0) {
|
||||
// Update the fields -- json config field will be updated later
|
||||
dbUpdate($details, 'alert_transports', 'transport_id=?', [$transport_id]);
|
||||
} else {
|
||||
// Insert the new alert transport
|
||||
$newEntry = true;
|
||||
$transport_id = dbInsert($details, 'alert_transports');
|
||||
}
|
||||
|
||||
if ($transport_id) {
|
||||
$class = 'LibreNMS\\Alert\\Transport\\'.ucfirst($transport_type);
|
||||
|
||||
if (!method_exists($class, 'configTemplate')) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'This transport type is not yet supported'
|
||||
]));
|
||||
}
|
||||
|
||||
// Build config values
|
||||
$result = call_user_func_array($class.'::configTemplate', []);
|
||||
$loader = new FileLoader(new Filesystem, "$install_dir/resources/lang");
|
||||
$translator = new Translator($loader, 'en');
|
||||
$validation = new Factory($translator, new Container);
|
||||
$validator = $validation->make($vars, $result['validation']);
|
||||
if ($validator->fails()) {
|
||||
$errors = $validator->errors();
|
||||
foreach ($errors->all() as $error) {
|
||||
$message .= "$error<br>";
|
||||
}
|
||||
$status = 'error';
|
||||
} else {
|
||||
foreach ($result['config'] as $tmp_config) {
|
||||
$transport_config[$tmp_config['name']] = $vars[$tmp_config['name']];
|
||||
}
|
||||
//Update the json config field
|
||||
if ($transport_config) {
|
||||
$transport_config = json_encode($transport_config);
|
||||
$detail = array(
|
||||
'transport_type' => $transport_type,
|
||||
'transport_config' => $transport_config
|
||||
);
|
||||
$where = 'transport_id=?';
|
||||
|
||||
dbUpdate($detail, 'alert_transports', $where, [$transport_id]);
|
||||
|
||||
$status = 'ok';
|
||||
$message = 'Updated alert transports';
|
||||
} else {
|
||||
$status = 'error';
|
||||
$message = 'There was an issue with the transport config';
|
||||
}
|
||||
}
|
||||
if ($status == 'error' && $newEntry) {
|
||||
//If error, we will have to delete the new entry in alert_transports tbl
|
||||
$where = '`transport_id`=?';
|
||||
dbDelete('alert_transports', $where, [$transport_id]);
|
||||
}
|
||||
} else {
|
||||
$status = 'error';
|
||||
$message = 'Failed to update transport';
|
||||
}
|
||||
}
|
||||
|
||||
die(json_encode([
|
||||
'status' => $status,
|
||||
'message' => $message
|
||||
]));
|
@@ -20,14 +20,14 @@ if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die('ERROR: You need to be admin');
|
||||
}
|
||||
|
||||
if (!is_numeric($_POST['alert_id'])) {
|
||||
if (!is_numeric($vars['alert_id'])) {
|
||||
echo 'ERROR: No alert selected';
|
||||
exit;
|
||||
} else {
|
||||
if (dbDelete('alert_rules', '`id` = ?', array($_POST['alert_id']))) {
|
||||
dbDelete('alert_device_map', 'rule_id=?', [$_POST['alert_id']]);
|
||||
dbDelete('alert_group_map', 'rule_id=?', [$_POST['alert_id']]);
|
||||
|
||||
if (dbDelete('alert_rules', '`id` = ?', array($vars['alert_id']))) {
|
||||
dbDelete('alert_device_map', 'rule_id=?', [$vars['alert_id']]);
|
||||
dbDelete('alert_group_map', 'rule_id=?', [$vars['alert_id']]);
|
||||
dbDelete('alert_transport_map', 'rule_id=?', [$vars['alert_id']]);
|
||||
echo 'Alert rule has been deleted.';
|
||||
exit;
|
||||
} else {
|
||||
|
44
html/includes/forms/delete-alert-transport.inc.php
Normal file
44
html/includes/forms/delete-alert-transport.inc.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'ERROR: You need to be admin.'
|
||||
]));
|
||||
}
|
||||
|
||||
$status = 'ok';
|
||||
$message = '';
|
||||
|
||||
if (!is_numeric($vars['transport_id'])) {
|
||||
$status = 'error';
|
||||
$message = 'ERROR: No transport selected';
|
||||
} else {
|
||||
if (dbDelete('alert_transports', '`transport_id` = ?', [$vars['transport_id']])) {
|
||||
dbDelete('alert_transport_map', '`target_type` = "single" AND `transport_or_group_id` = ?', [$vars['transport_id']]);
|
||||
dbDelete('transport_group_transport', '`transport_id`=?', [$vars['transport_id']]);
|
||||
|
||||
$message = 'Alert transport has been deleted';
|
||||
} else {
|
||||
$message = 'ERROR: Alert transport has not been deleted';
|
||||
}
|
||||
}
|
||||
|
||||
die(json_encode([
|
||||
'status' => $status,
|
||||
'message'=> $message
|
||||
]));
|
45
html/includes/forms/delete-transport-group.inc.php
Normal file
45
html/includes/forms/delete-transport-group.inc.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'ERROR: You need to be admin.'
|
||||
]));
|
||||
}
|
||||
|
||||
$status = 'ok';
|
||||
$message = '';
|
||||
|
||||
if (!is_numeric($vars['group_id'])) {
|
||||
$status = 'error';
|
||||
$message = 'ERROR: No transport group selected';
|
||||
} else {
|
||||
if (dbDelete('alert_transport_groups', '`transport_group_id` = ?', [$vars['group_id']])) {
|
||||
dbDelete('transport_group_transport', '`transport_group_id`=?', [$vars['group_id']]);
|
||||
dbDelete('alert_transport_map', '`target_type`="group" AND `transport_or_group_id`=?', [$vars['group_id']]);
|
||||
$message = 'Alert transport group has been deleted';
|
||||
} else {
|
||||
$message = 'ERROR: Alert transport group has not been deleted';
|
||||
}
|
||||
}
|
||||
|
||||
die(json_encode([
|
||||
'status' => $status,
|
||||
'message'=> $message
|
||||
]));
|
@@ -19,9 +19,8 @@ if (!Auth::user()->hasGlobalAdmin()) {
|
||||
header('Content-type: text/plain');
|
||||
die('ERROR: You need to be admin');
|
||||
}
|
||||
|
||||
$alert_id = $_POST['alert_id'];
|
||||
$template_id = $_POST['template_id'];
|
||||
$alert_id = $vars['alert_id'];
|
||||
$template_id = $vars['template_id'];
|
||||
|
||||
if (is_numeric($alert_id) && $alert_id > 0) {
|
||||
$rule = dbFetchRow('SELECT * FROM `alert_rules` WHERE `id` = ? LIMIT 1', [$alert_id]);
|
||||
@@ -37,6 +36,24 @@ if (is_numeric($alert_id) && $alert_id > 0) {
|
||||
foreach ($groups as $group) {
|
||||
$maps[] = ['id' => 'g' . $group['group_id'], 'text' => $group['name']];
|
||||
}
|
||||
|
||||
$transports = [];
|
||||
$members = dbFetchRows('SELECT `transport_or_group_id`, `transport_name`, `transport_type` FROM `alert_transport_map` LEFT JOIN `alert_transports` ON `transport_or_group_id` = `transport_id` WHERE `target_type`="single" AND `rule_id`=?', [$alert_id]);
|
||||
|
||||
foreach ($members as $member) {
|
||||
$transports[] = [
|
||||
'id' => $member['transport_or_group_id'],
|
||||
'text' => ucfirst($member['transport_type']).": ".$member['transport_name']
|
||||
];
|
||||
}
|
||||
|
||||
$t_groups = dbFetchRows('SELECT `transport_or_group_id`, `transport_group_name` FROM `alert_transport_map` LEFT JOIN `alert_transport_groups` ON `transport_or_group_id`=`transport_group_id` WHERE `target_type`="group" AND `rule_id`=?', [$alert_id]);
|
||||
foreach ($t_groups as $group) {
|
||||
$transports[] = [
|
||||
'id' => 'g'.$group['transport_or_group_id'],
|
||||
'text' => 'Group: '.$group['transport_group_name']
|
||||
];
|
||||
}
|
||||
} elseif (is_numeric($template_id) && $template_id >= 0) {
|
||||
$tmp_rules = get_rules_from_json();
|
||||
$rule = $tmp_rules[$template_id];
|
||||
@@ -55,6 +72,7 @@ if (is_array($rule)) {
|
||||
echo json_encode([
|
||||
'extra' => isset($rule['extra']) ? json_decode($rule['extra']) : null,
|
||||
'maps' => $maps,
|
||||
'transports' => $transports,
|
||||
'name' => $rule['name'],
|
||||
'proc' => $rule['proc'],
|
||||
'builder' => $builder,
|
||||
|
56
html/includes/forms/show-alert-transport.inc.php
Normal file
56
html/includes/forms/show-alert-transport.inc.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'ERROR: You need to be admin'
|
||||
]));
|
||||
}
|
||||
|
||||
$transport_id = $vars['transport_id'];
|
||||
// Retrieve alert transport
|
||||
if (is_numeric($transport_id) && $transport_id > 0) {
|
||||
$transport = dbFetchRow('SELECT * FROM `alert_transports` WHERE `transport_id` =? LIMIT 1', [$transport_id]);
|
||||
|
||||
if ($transport['is_default'] == true) {
|
||||
$is_default = true;
|
||||
} else {
|
||||
$is_default = false;
|
||||
}
|
||||
$details = [];
|
||||
// Get alert transport configuration details
|
||||
foreach (json_decode($transport['transport_config'], true) as $key => $value) {
|
||||
$details[] = [
|
||||
'name' => $key,
|
||||
'value' => $value
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($transport)) {
|
||||
die(json_encode([
|
||||
'name' => $transport['transport_name'],
|
||||
'type' => $transport['transport_type'],
|
||||
'is_default' => $is_default,
|
||||
'details' => $details
|
||||
]));
|
||||
} else {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'ERROR: No alert transport found'
|
||||
]));
|
||||
}
|
50
html/includes/forms/show-transport-group.inc.php
Normal file
50
html/includes/forms/show-transport-group.inc.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'ERROR: You need to be admin'
|
||||
]));
|
||||
}
|
||||
|
||||
$group_id = $vars['group_id'];
|
||||
// Retrieve alert transport
|
||||
if (is_numeric($group_id) && $group_id > 0) {
|
||||
$name = dbFetchCell('SELECT `transport_group_name` FROM `alert_transport_groups` WHERE `transport_group_id`=? LIMIT 1', [$group_id]);
|
||||
|
||||
$query = "SELECT `a`.`transport_id`, `transport_type`, `transport_name` FROM `transport_group_transport` AS `a` LEFT JOIN `alert_transports` AS `b` ON `a`.`transport_id`=`b`.`transport_id` WHERE `transport_group_id`=?";
|
||||
|
||||
$members = [];
|
||||
foreach (dbFetchRows($query, [$group_id]) as $member) {
|
||||
$members[] = [
|
||||
'id' => $member['transport_id'],
|
||||
'text' => ucfirst($member['transport_type']).": ".$member['transport_name']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($members)) {
|
||||
die(json_encode([
|
||||
'name' => $name,
|
||||
'members' => $members
|
||||
]));
|
||||
} else {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'ERROR: No transport group found'
|
||||
]));
|
||||
}
|
@@ -19,7 +19,8 @@ if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die('ERROR: You need to be admin');
|
||||
}
|
||||
|
||||
$transport = mres($_POST['transport']);
|
||||
$transport = $vars['transport'] ?: null;
|
||||
$transport_id = $vars['transport_id'] ?: null;
|
||||
|
||||
require_once $config['install_dir'].'/includes/alerts.inc.php';
|
||||
$tmp = array(dbFetchRow('select device_id,hostname,sysDescr,version,hardware,location from devices order by device_id asc limit 1'));
|
||||
@@ -37,7 +38,7 @@ $obj = array(
|
||||
"faults" => false,
|
||||
"uid" => "000",
|
||||
"severity" => "critical",
|
||||
"rule" => "%macros.device = 1",
|
||||
"rule" => "macros.device = 1",
|
||||
"name" => "Test-Rule",
|
||||
"string" => "#1: test => string;",
|
||||
"timestamp" => date("Y-m-d H:i:s"),
|
||||
@@ -48,11 +49,14 @@ $obj = array(
|
||||
|
||||
$status = 'error';
|
||||
|
||||
if ($transport_id) {
|
||||
$transport = dbFetchCell("SELECT `transport_type` FROM `alert_transports` WHERE `transport_id` = ?", [$transport_id]);
|
||||
}
|
||||
$class = 'LibreNMS\\Alert\\Transport\\' . ucfirst($transport);
|
||||
if (class_exists($class)) {
|
||||
$opts = $config['alert']['transports'][$transport];
|
||||
if ($opts) {
|
||||
$instance = new $class;
|
||||
$instance = new $class($transport_id);
|
||||
$tmp = $instance->deliverAlert($obj, $opts);
|
||||
if ($tmp) {
|
||||
$status = 'ok';
|
||||
|
101
html/includes/forms/transport-groups.inc.php
Normal file
101
html/includes/forms/transport-groups.inc.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* transport-groups.inc.php
|
||||
*
|
||||
* LibreNMS alert-transportsinc.php for processor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2018 Vivia Nguyen-Tran
|
||||
* @author Vivia Nguyen-Tran <vivia@ualberta.ca>
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
if (!Auth::user()->hasGlobalAdmin()) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'You need to be admin'
|
||||
]));
|
||||
}
|
||||
|
||||
$status = 'ok';
|
||||
$message = '';
|
||||
|
||||
$group_id = $vars['group_id'];
|
||||
$name = $vars['name'];
|
||||
|
||||
$target_members = [];
|
||||
foreach ((array)$vars['members'] as $target) {
|
||||
$target_members[] = (int)$target;
|
||||
}
|
||||
|
||||
if (empty($name)) {
|
||||
$status = 'error';
|
||||
$message = 'No transport group name provided';
|
||||
} elseif (sizeof($target_members) < 1) {
|
||||
// Not enough members for a group; requires 1 at least
|
||||
$status = 'error';
|
||||
$message = 'Not enough group members';
|
||||
} else {
|
||||
if (is_numeric($group_id) && $group_id > 0) {
|
||||
dbUpdate(array(
|
||||
'transport_group_name' => $name
|
||||
), 'alert_transport_groups', "`transport_group_id`=?", [$group_id]);
|
||||
} else {
|
||||
// Insert into db
|
||||
$group_id = dbInsert(array(
|
||||
'transport_group_name' => $name
|
||||
), 'alert_transport_groups');
|
||||
}
|
||||
|
||||
if (is_numeric($group_id) && $group_id > 0) {
|
||||
$sql = "SELECT `transport_id` FROM `transport_group_transport` WHERE `transport_group_id`=?";
|
||||
$db_members = dbFetchColumn($sql, [$group_id]);
|
||||
|
||||
// Compare arrays to get added and removed transports
|
||||
$add = array_diff($target_members, $db_members);
|
||||
$remove = array_diff($db_members, $target_members);
|
||||
|
||||
// Insert new transport group members
|
||||
$insert = [];
|
||||
foreach ($add as $transport_id) {
|
||||
$insert[] = array(
|
||||
'transport_id' => $transport_id,
|
||||
'transport_group_id' => $group_id
|
||||
);
|
||||
}
|
||||
if (!empty($insert)) {
|
||||
dbBulkInsert($insert, 'transport_group_transport');
|
||||
}
|
||||
|
||||
// Remove old transport group members
|
||||
if (!empty($remove)) {
|
||||
dbDelete('transport_group_transport', 'transport_group_id=? AND `transport_id` IN (?)', array($group_id, array(implode(',', $remove))));
|
||||
}
|
||||
$message = 'Updated alert transport group';
|
||||
} else {
|
||||
$status = 'error';
|
||||
$message = 'Did not update alert transport group';
|
||||
}
|
||||
}
|
||||
|
||||
die(json_encode([
|
||||
'status' => $status,
|
||||
'message' => $message
|
||||
]));
|
66
html/includes/list/transport_groups.inc.php
Normal file
66
html/includes/list/transport_groups.inc.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* transport-groups.inc.php
|
||||
*
|
||||
* List transports and transport groups
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2018 Vivia Nguyen-Tran
|
||||
* @author Vivia Nguyen-Tran <vivia@ualberta>
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
if (!Auth::user()->hasGlobalRead()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
list($transports, $t_more) = include 'transports.inc.php';
|
||||
|
||||
$query = '';
|
||||
$params = [];
|
||||
|
||||
if (!empty($_REQUEST['search'])) {
|
||||
$query .= ' WHERE `transport_group_name` LIKE ?';
|
||||
$params[] = '%' . mres($_REQUEST['search']) . '%';
|
||||
}
|
||||
|
||||
$total = dbFetchCell("SELECT COUNT(*) FROM `alert_transport_groups` $query", $params);
|
||||
$more = false;
|
||||
|
||||
if (!empty($_REQUEST['limit'])) {
|
||||
$limit = (int) $_REQUEST['limit'];
|
||||
$page = isset($_REQUEST['page']) ? (int) $_REQUEST['page'] : 1;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$query .= " LIMIT $offset, $limit";
|
||||
} else {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$sql = "SELECT `transport_group_id` AS `id`, `transport_group_name` AS `text` FROM `alert_transport_groups` $query";
|
||||
$groups = dbFetchRows($sql, $params);
|
||||
$more = ($offset + count($groups))<$total;
|
||||
$groups = array_map(function ($group) {
|
||||
$group['text'] = "Group: ".$group['text'];
|
||||
$group['id'] = "g".$group['id'];
|
||||
return $group;
|
||||
}, $groups);
|
||||
|
||||
$data = [['text' => 'Transport Groups', 'children' => $groups], $transports[0]];
|
||||
|
||||
return[$data, $more || $c_more];
|
64
html/includes/list/transports.inc.php
Normal file
64
html/includes/list/transports.inc.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* transports.inc.php
|
||||
*
|
||||
* List transports
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2018 Vivia Nguyen-Tran
|
||||
* @author Vivia Nguyen-Tran <vivia@ualberta>
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
if (!Auth::user()->hasGlobalRead()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$query = '';
|
||||
$params = [];
|
||||
|
||||
if (!empty($_REQUEST['search'])) {
|
||||
$query .= ' WHERE `transport_name` LIKE ?';
|
||||
$params[] = '%' . mres($_REQUEST['search']) . '%';
|
||||
}
|
||||
|
||||
$total = dbFetchCell("SELECT COUNT(*) FROM `alert_transports` $query", $params);
|
||||
$more = false;
|
||||
|
||||
if (!empty($_REQUEST['limit'])) {
|
||||
$limit = (int) $_REQUEST['limit'];
|
||||
$page = isset($_REQUEST['page']) ? (int) $_REQUEST['page'] : 1;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$query .= " LIMIT $offset, $limit";
|
||||
} else {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$sql = "SELECT `transport_id` AS `id`, `transport_name` AS `text`, `transport_type` AS `type` FROM `alert_transports` $query";
|
||||
$transports = dbFetchRows($sql, $params);
|
||||
|
||||
$more = ($offset + count($transports))<$total;
|
||||
$transports = array_map(function ($transport) {
|
||||
$transport['text'] = ucfirst($transport['type']).": ".$transport['text'];
|
||||
unset($transport['type']);
|
||||
return $transport;
|
||||
}, $transports);
|
||||
|
||||
$data = [['text' => 'Transports', 'children' => $transports]];
|
||||
return[$data, $more];
|
306
html/includes/modal/edit_alert_transport.inc.php
Normal file
306
html/includes/modal/edit_alert_transport.inc.php
Normal file
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* Copyright (c) 2018 Vivia Nguyen-Tran <vivia@ualberta.ca>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use LibreNMS\Config;
|
||||
|
||||
if (Auth::user()->hasGlobalAdmin()) {
|
||||
?>
|
||||
<!--Modal for adding or updating an alert transport -->
|
||||
<div class="modal fade" id="edit-alert-transport" tabindex="-1" role="dialog"
|
||||
aria-labelledby="Edit-transport" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h5 class="modal-title" id="Edit-transport">Alert Transport :: <a href="https://docs.librenms.org/Alerting/">Docs <i class="fa fa-book fa-1x"></i></a> </h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="post" role="form" id="transports" class="form-horizontal transports-form">
|
||||
<input type="hidden" name="transport_id" id="transport_id" value="">
|
||||
<input type="hidden" name="type" id="type" value="alert-transports">
|
||||
<div class='form-group' title="The description of this alert transport.">
|
||||
<label for='name' class='col-sm-3 col-md-2 control-label'>Transport name: </label>
|
||||
<div class='col-sm-9 col-md-10'>
|
||||
<input type='text' id='name' name='name' class='form-control validation' maxlength='200' required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" title="The type of transport.">
|
||||
<label for='transport-choice' class='col-sm-3 col-md-2 control-label'>Transport type: </label>
|
||||
<div class="col-sm-3">
|
||||
<select name='transport-choice' id='transport-choice' class='form-control'>
|
||||
<option value="api-form">API</option>
|
||||
<option value="boxcar-form">Boxcar</option>
|
||||
<option value="canopsis-form">Canopsis</option>
|
||||
<option value="ciscospark-form">Cisco Spark</option>
|
||||
<option value="clickatell-form">Clickatell</option>
|
||||
<option value="discord-form">Discord</option>
|
||||
<option value="elasticsearch-form">Elasticsearch</option>
|
||||
<option value="gitlab-form">Gitlab</option>
|
||||
<option value="hipchat-form">Hipchat</option>
|
||||
<option value="irc-form">IRC</option>
|
||||
<option value="jira-form">Jira</option>
|
||||
<option value="mail-form" selected>Mail</option>
|
||||
<option value="msteams-form">Microsoft Teams</option>
|
||||
<option value="nagios-form">Nagios</option>
|
||||
<option value="opsgenie-form">OpsGenie</option>
|
||||
<option value="osticket-form">osTicket</option>
|
||||
<option value="hue-form">Phillips Hue</option>
|
||||
<option value="playsms-form">PlaySMS</option>
|
||||
<option value="pushbullet-form">Pushbullet</option>
|
||||
<option value="pushover-form">Pushover</option>
|
||||
<option value="rocket-form">Rocket.chat</option>
|
||||
<option value="slack-form">Slack</option>
|
||||
<option value="smseagle-form">SMSEagle</option>
|
||||
<option value="syslog-form">Syslog</option>
|
||||
<option value="telegram-form">Telegram</option>
|
||||
<option value="victorops-form">Victorops</option>
|
||||
<!--Insert more transport type options here has support is added. Value should be: [transport_name]-form -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" title="The transport is default.">
|
||||
<label for="default" class="col-sm-3 col-md-2 control-label">Default Alert: </label>
|
||||
<div class="col-sm-2">
|
||||
<input type="checkbox" name="is_default" id="is_default">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
|
||||
// Fetch list of transport classes
|
||||
$transport_dir = Config::get('install_dir').'/LibreNMS/Alert/Transport';
|
||||
$switches = []; // store names of bootstrap switches
|
||||
|
||||
foreach (scandir($transport_dir) as $transport) {
|
||||
$transport = strstr($transport, '.', true);
|
||||
if (empty($transport)) {
|
||||
continue;
|
||||
}
|
||||
$class = 'LibreNMS\\Alert\\Transport\\'.$transport;
|
||||
|
||||
if (!method_exists($class, 'configTemplate')) {
|
||||
// Skip since support has not been added
|
||||
continue;
|
||||
}
|
||||
|
||||
echo '<form method="post" role="form" id="'.strtolower($transport).'-form" class="form-horizontal transport">';
|
||||
echo '<input type="hidden" name="transport-type" id="transport-type" value="'.strtolower($transport).'">';
|
||||
|
||||
$tmp = call_user_func($class.'::configTemplate');
|
||||
|
||||
foreach ($tmp['config'] as $item) {
|
||||
echo '<div class="form-group" title="'.$item['descr'].'">';
|
||||
echo '<label for="'.$item['name'].'" class="col-sm-3 col-md-2 control-label">'.$item['title'].': </label>';
|
||||
if ($item['type'] == 'text') {
|
||||
echo '<div class="col-sm-9 col-md-10">';
|
||||
echo '<input type="'.$item['type'].'" id="'.$item['name'].'" name="'.$item['name'].'" class="form-control" ';
|
||||
if ($item['required']) {
|
||||
echo 'required>';
|
||||
} else {
|
||||
echo '>';
|
||||
}
|
||||
echo '</div>';
|
||||
} elseif ($item['type'] == 'checkbox') {
|
||||
echo '<div class="col-sm-2">';
|
||||
echo '<input type="checkbox" name="'.$item['name'].'" id="'.$item['name'].'">';
|
||||
echo '</div>';
|
||||
$switches[$item['name']] = $item['default'];
|
||||
} elseif ($item['type'] == 'select') {
|
||||
echo '<div class="col-sm-3">';
|
||||
echo '<select name="'.$item['name'].'" id="'.$item['name'].'" class="form-control">';
|
||||
foreach ($item['options'] as $descr => $opt) {
|
||||
echo '<option value="'.$opt.'">'.$descr.'</option>';
|
||||
}
|
||||
echo '</select>';
|
||||
echo '</div>';
|
||||
} elseif ($item['type'] === 'textarea') {
|
||||
echo '<div class="col-sm-9 col-md-10">';
|
||||
echo '<textarea name="' . $item['name'] . '" id="' . $item['name'] . '" class="form-control" placeholder="'.$item['descr'].'">';
|
||||
echo '</textarea>';
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
echo '<div class="form-group">';
|
||||
echo '<div class="col-sm-12 text-center">';
|
||||
echo '<button type="button" class="btn btn-success btn-save" name="save-transport">';
|
||||
echo 'Save Transport';
|
||||
echo '</button>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</form>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modal end for adding or updating an alert tramsport-->
|
||||
|
||||
<!--Modal for deleting an alert transport -->
|
||||
<div class="modal fade" id="delete-alert-transport" 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">×</button>
|
||||
<h5 class="modal-title" id="Delete">Confirm Transport Delete</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>If you would like to remove this alert transport then please click Delete.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<form role="form" class="remove_transport_form">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-danger danger" id="remove-alert-transport" data-target="remove-alert-transport">Delete</button>
|
||||
<input type="hidden" name="transport_id" id="delete_transport_id" value="">
|
||||
<input type="hidden" name="confirm" id="confirm" value="yes">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Modal end for deleting an alert transport -->
|
||||
|
||||
<script>
|
||||
// Scripts related to editing/updating alert transports
|
||||
|
||||
// Display different form on selection
|
||||
$("#transport-choice").change(function (){
|
||||
$(".transport").hide();
|
||||
$("#" + $(this).val()).show().find("input:text").val("");
|
||||
|
||||
});
|
||||
|
||||
$("#edit-alert-transport").on("show.bs.modal", function(e) {
|
||||
// Get transport id of clicked element
|
||||
var transport_id = $(e.relatedTarget).data("transport_id");
|
||||
$("#transport_id").val(transport_id);
|
||||
if(transport_id > 0) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: { type: "show-alert-transport", transport_id: transport_id },
|
||||
success: function (data) {
|
||||
loadTransport(data);
|
||||
},
|
||||
error: function () {
|
||||
toastr.error("Failed to process alert transport");
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
// Resetting to default
|
||||
$("#name").val("");
|
||||
$("#transport-choice").val("mail-form");
|
||||
$(".transport").hide();
|
||||
$("#" + $("#transport-choice").val()).show().find("input:text").val("");
|
||||
$("#is_default").bootstrapSwitch('state', false);
|
||||
|
||||
// Turn on all switches in form
|
||||
var switches = <?php echo json_encode($switches);?>;
|
||||
$.each(switches, function(name, state) {
|
||||
$("input[name="+name+"]").bootstrapSwitch('state', state);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function loadTransport(transport) {
|
||||
$("#name").val(transport.name);
|
||||
$("#transport-choice").val(transport.type+"-form");
|
||||
$("#is_default").bootstrapSwitch('state', transport.is_default);
|
||||
$(".transport").hide();
|
||||
$("#" + $("#transport-choice").val()).show().find("input:text").val("");
|
||||
|
||||
// Populate the field values
|
||||
transport.details.forEach(function(config) {
|
||||
var $field = $("#" + config.name);
|
||||
if ($field.prop('type') == 'checkbox') {
|
||||
$field.bootstrapSwitch('state', config.value);
|
||||
} else {
|
||||
$field.val(config.value);
|
||||
$("#options").val('dasdsaddasdsa');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Save alert transport
|
||||
$(".btn-save").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
//Combine form data (general and transport specific)
|
||||
data = $("form.transports-form").serializeArray();
|
||||
data = data.concat($("#" + $("#transport-choice").val()).serializeArray());
|
||||
|
||||
if (data !== null) {
|
||||
//post data to ajax form
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: data,
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.status == 'ok') {
|
||||
toastr.success(data.message);
|
||||
setTimeout(function (){
|
||||
$("#edit-alert-transports").modal("hide");
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
} else {
|
||||
toastr.error(data.message);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
toastr.error("Failed to process alert transport");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Scripts related to deleting an alert transport
|
||||
|
||||
// Populate transport id value
|
||||
$("#delete-alert-transport").on("show.bs.modal", function(event) {
|
||||
transport_id = $(event.relatedTarget).data("transport_id");
|
||||
$("#delete_transport_id").val(transport_id);
|
||||
});
|
||||
|
||||
// Delete the alert transport
|
||||
$("#remove-alert-transport").click('', function(event) {
|
||||
event.preventDefault();
|
||||
var transport_id = $("#delete_transport_id").val();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: { type: "delete-alert-transport", transport_id: transport_id },
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if (data.status == 'ok') {
|
||||
toastr.success(data.message);
|
||||
$("#alert-transport-" + transport_id).remove();
|
||||
$("#delete-alert-transport").modal("hide");
|
||||
} else {
|
||||
toastr.error(data.message);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
toastr.error("The alert transport could not be deleted.");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<?php
|
||||
}
|
187
html/includes/modal/edit_transport_group.inc.php
Normal file
187
html/includes/modal/edit_transport_group.inc.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* Copyright (c) 2018 Vivia Nguyen-Tran <vivia@ualberta.ca>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
if (Auth::user()->hasGlobalAdmin()) {
|
||||
?>
|
||||
<!--Modal for adding or updating a transport group -->
|
||||
<div class="modal fade" id="edit-transport-group" tabindex="-1" role="dialog"
|
||||
aria-labelledby="Edit-transport" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h5 class="modal-title" id="Edit-transport">Alert Transport Groups :: <a href="https://docs.librenms.org/Alerting/">Docs <i class="fa fa-book fa-1x"></i></a> </h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="post" role="form" id="transport-group" class="form-horizontal transport-group-form">
|
||||
<input type="hidden" name="group_id" id="group_id" value="">
|
||||
<input type="hidden" name="type" id="type" value="transport-groups">
|
||||
<div class='form-group' title="The description of this transport group.">
|
||||
<label for='name' class='col-sm-3 col-md-2 control-label'>Group Name: </label>
|
||||
<div class='col-sm-9 col-md-10'>
|
||||
<input type='text' id='group-name' name='name' class='form-control validation' maxlength='200' required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" title="The members for this transport group.">
|
||||
<label for='transport-choice' class='col-sm-3 col-md-2 control-label'>Group Members: </label>
|
||||
<div class="col-sm-9 col-md-10">
|
||||
<select name='members[]' id='members' class='form-control' multiple="multiple"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12 text-center">
|
||||
<button type="button" class="btn btn-success" id="save-group" name="save-group">
|
||||
Save Transport Group
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modal end for adding or updating an alert transport-->
|
||||
|
||||
<!-- Modal for deleting transport group -->
|
||||
<div class="modal fade" id="delete-transport-group" 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">×</button>
|
||||
<h5 class="modal-title" id="Delete">Confirm Group Delete</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>If you would like to remove this transport group then please click Delete.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<form role="form" class="remove_contract_group">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger danger" id="remove-transport-group" data-target="remove-transport-group">Delete</button>
|
||||
<input type="hidden" name="group_id" id="delete_group_id" value="">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modal end for deleting transport group-->
|
||||
|
||||
<script>
|
||||
$("#edit-transport-group").on("show.bs.modal", function (e) {
|
||||
// Get group-id of the clicked element
|
||||
var group_id = $(e.relatedTarget).data("group_id");
|
||||
$("#group_id").val(group_id);
|
||||
|
||||
// Reset form
|
||||
$(this).find("input[type=text]").val("");
|
||||
var $members = $("#members");
|
||||
$members.empty();
|
||||
$members.val(null).trigger('change');
|
||||
|
||||
if (group_id > 0) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: { type: "show-transport-group", group_id: group_id},
|
||||
success: function (group) {
|
||||
$("#group-name").val(group.name);
|
||||
$.each(group.members, function(index, value) {
|
||||
var option = new Option(value.text, value.id, true, true);
|
||||
$members.append(option).trigger("change");
|
||||
});
|
||||
},
|
||||
error: function () {
|
||||
toastr.error("Failed to process transport group");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#save-group").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
data = $("form.transport-group-form").serializeArray();
|
||||
if (data != null) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: data,
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.status == 'ok') {
|
||||
toastr.success(data.message);
|
||||
setTimeout(function () {
|
||||
$("edit-transport-group").modal("hide");
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
} else {
|
||||
toastr.error(data.message);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
toastr.error("Failed to proccess transport group");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#members").select2({
|
||||
width: "100%",
|
||||
placeholder: "Transport Name",
|
||||
ajax: {
|
||||
url: 'ajax_list.php',
|
||||
delay: 250,
|
||||
data: function(params) {
|
||||
return {
|
||||
type: "transports",
|
||||
search: params.term
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Populate group id value
|
||||
$("#delete-transport-group").on("show.bs.modal", function (event) {
|
||||
group_id = $(event.relatedTarget).data("group_id");
|
||||
$("#delete_group_id").val(group_id);
|
||||
});
|
||||
|
||||
// Delete the transport group
|
||||
$("#remove-transport-group").click('', function (event) {
|
||||
event.preventDefault();
|
||||
var group_id = $("#delete_group_id").val();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: { type: "delete-transport-group", group_id: group_id},
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if (data.status == 'ok') {
|
||||
toastr.success(data.message);
|
||||
$("#alert-transport-group-" + group_id).remove();
|
||||
$("#delete-transport-group").modal("hide");
|
||||
} else {
|
||||
toastr.error(data.message);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
toastr.error("The alert transport could not be deleted.");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<?php
|
||||
}
|
@@ -109,6 +109,12 @@ if (Auth::user()->hasGlobalAdmin()) {
|
||||
<select id="maps" name="maps[]" class="form-control" multiple="multiple"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" title="Restricts this alert rule to specified transports.">
|
||||
<label for="transports" class="col-sm-3 col-md-2 control-label">Transports: </label>
|
||||
<div class="col-sm-9 col-md-10">
|
||||
<select id="transports" name="transports[]" class="form-control" multiple="multiple"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class='form-group' title="A link to some documentation on how to handle this alert. This will be included in notifications.">
|
||||
<label for='proc' class='col-sm-3 col-md-2 control-label'>Procedure URL: </label>
|
||||
<div class='col-sm-9 col-md-10'>
|
||||
@@ -123,8 +129,6 @@ if (Auth::user()->hasGlobalAdmin()) {
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -274,6 +278,11 @@ if (Auth::user()->hasGlobalAdmin()) {
|
||||
$maps.empty();
|
||||
$maps.val(null).trigger('change');
|
||||
setRuleDevice() // pre-populate device in the maps if this is a per-device rule
|
||||
|
||||
var $transports = $("#transports");
|
||||
$transports.empty();
|
||||
$transports.val(null).trigger('change');
|
||||
$("#transport-choice").val("email");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -295,6 +304,15 @@ if (Auth::user()->hasGlobalAdmin()) {
|
||||
$maps.append(option).trigger('change')
|
||||
});
|
||||
}
|
||||
var $transports = $("#transports");
|
||||
$transports.empty();
|
||||
$transports.val(null).trigger('change');
|
||||
if(rule.transports != null) {
|
||||
$.each(rule.transports, function(index, value) {
|
||||
var option = new Option(value.text, value.id, true, true);
|
||||
$transports.append(option).trigger("change");
|
||||
});
|
||||
}
|
||||
|
||||
if (rule.extra != null) {
|
||||
var extra = rule.extra;
|
||||
@@ -354,6 +372,21 @@ if (Auth::user()->hasGlobalAdmin()) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#transports").select2({
|
||||
width: "100%",
|
||||
placeholder: "Transport/Group Name",
|
||||
ajax: {
|
||||
url: 'ajax_list.php',
|
||||
delay: 250,
|
||||
data: function(params) {
|
||||
return {
|
||||
type: "transport_groups",
|
||||
search: params.term
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
163
html/includes/print-alert-transports.php
Normal file
163
html/includes/print-alert-transports.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
$no_refresh = true;
|
||||
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<span id="message"></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
require_once 'includes/modal/edit_alert_transport.inc.php';
|
||||
require_once 'includes/modal/edit_transport_group.inc.php';
|
||||
|
||||
?>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Transport Name</th>
|
||||
<th>Transport Type</th>
|
||||
<th>Default</th>
|
||||
<th>Details</th>
|
||||
<th style="width:126px;">Action</th>
|
||||
</tr>
|
||||
<td colspan="6">
|
||||
<?php
|
||||
if (Auth::user()->hasGlobalAdmin()) {
|
||||
echo "<button type='button' class='btn btn-primary btn-sm' data-toggle='modal' data-target='#edit-alert-transport'><i class='fa fa-plus'></i> Create alert transport</button>";
|
||||
}
|
||||
|
||||
echo "</td>";
|
||||
|
||||
// Iterate through each alert transport
|
||||
$query = "SELECT `transport_id` AS `id`, `transport_name` AS `name`, `transport_type` AS `type`, `is_default`, `transport_config` AS `config` FROM `alert_transports`";
|
||||
foreach (dbFetchRows($query) as $transport) {
|
||||
echo "<tr id=\"alert-transport-{$transport['id']}\">";
|
||||
echo "<td><i>#".((int)$transport['id'])."</i></td>";
|
||||
echo "<td>".$transport['name']."</td>";
|
||||
echo "<td>".$transport['type']."</td>";
|
||||
if ($transport['is_default'] == true) {
|
||||
echo "<td>Yes</td>";
|
||||
} else {
|
||||
echo "<td>No</td>";
|
||||
}
|
||||
|
||||
echo "<td class='col-sm-4'>";
|
||||
|
||||
// Iterate through transport config template to display config details
|
||||
$class = 'LibreNMS\\Alert\\Transport\\'.ucfirst($transport['type']);
|
||||
if (!method_exists($class, 'configTemplate')) {
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
$tmp = call_user_func($class.'::configTemplate');
|
||||
$transport_config = json_decode($transport['config'], true);
|
||||
|
||||
foreach ($tmp['config'] as $item) {
|
||||
$val = $transport_config[$item['name']];
|
||||
|
||||
// Match value to key name for select inputs
|
||||
if ($item['type'] == 'select') {
|
||||
$val = array_search($val, $item['options']);
|
||||
}
|
||||
|
||||
echo "<i>".$item['title'].": ".$val."<br/></i>";
|
||||
}
|
||||
|
||||
echo "</td>";
|
||||
echo "<td>";
|
||||
|
||||
// Add action buttons for admin users only
|
||||
if (Auth::user()->hasGlobalAdmin()) {
|
||||
echo "<div class='btn-group btn-group-sm' role='group'>";
|
||||
echo "<button type='button' class='btn btn-primary' data-toggle='modal' data-target='#edit-alert-transport' data-transport_id='".$transport['id']."' name='edit-alert-rule' data-container='body' data-toggle='popover' data-content='Edit transport'><i class='fa fa-lg fa-pencil' aria-hidden='true'></i></button> ";
|
||||
echo "<button type='button' class='btn btn-danger' aria-label='Delete' data-toggle='modal' data-target='#delete-alert-transport' data-transport_id='".$transport['id']."' name='delete-alert-transport' data-container='body' data-toggle='popover' data-content='Delete transport'><i class='fa fa-lg fa-trash' aria-hidden='true'></i></button>";
|
||||
echo "<button type='button' class='btn btn-warning' data-transport_id='".$transport['id']."' data-transport='{$transport['type']}' name='test-transport' id='test-transport' data-toggle='popover' data-content='Test transport'><i class='fa fa-lg fa-check' aria-hidden='true'></i></button> ";
|
||||
echo "</div>";
|
||||
}
|
||||
echo "</td>";
|
||||
echo "</tr>\r\n";
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Transport Group</th>
|
||||
<th>Size</th>
|
||||
<th>Members</th>
|
||||
<th style="width:86px;">Action</th>
|
||||
</tr>
|
||||
<td colspan="5">
|
||||
<?php
|
||||
if (Auth::user()->hasGlobalAdmin()) {
|
||||
echo "<button type='button' class='btn btn-primary btn-sm' data-toggle='modal' data-target='#edit-transport-group'><i class='fa fa-plus'></i> Create transport group</button>";
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
//Iterate through alert groups
|
||||
$query = "SELECT `transport_group_id` AS `id`, `transport_group_name` AS `name` FROM `alert_transport_groups`";
|
||||
foreach (dbFetchRows($query) as $group) {
|
||||
echo "<tr id=\"alert-transport-group-{$group['id']}\">";
|
||||
echo "<td><i>#".((int)$group['id'])."</i></td>";
|
||||
echo "<td>".$group['name']."</td>";
|
||||
|
||||
//List out the members of each group
|
||||
$query = "SELECT `transport_type`, `transport_name` FROM `transport_group_transport` AS `a` LEFT JOIN `alert_transports` AS `b` ON `a`.`transport_id`=`b`.`transport_id` WHERE `transport_group_id`=?";
|
||||
$members = dbFetchRows($query, [$group['id']]);
|
||||
echo "<td>".sizeof($members)."</td>";
|
||||
echo "<td>";
|
||||
foreach ($members as $member) {
|
||||
echo "<i>".ucfirst($member['transport_type']).": ".$member['transport_name']."<br /></i>";
|
||||
}
|
||||
echo "</td>";
|
||||
echo "<td>";
|
||||
if (Auth::user()->hasGlobalAdmin()) {
|
||||
echo "<div class='btn-group btn-group-sm' role='group'>";
|
||||
echo "<button type='button' class='btn btn-primary' data-toggle='modal' data-target='#edit-transport-group' data-group_id='".$group['id']."' data-container='body' data-toggle='popover' data-content='Edit transport group'><i class='fa fa-lg fa-pencil' aria-hidden='true'></i></button> ";
|
||||
echo "<button type='button' class='btn btn-danger' aria-label='Delete' data-toggle='modal' data-target='#delete-transport-group' data-group_id='".$group['id']."' data-container='body' data-toggle='popover' data-content='Delete transport group'><i class='fa fa-lg fa-trash' aria-hidden='true'></i></button>";
|
||||
echo "</div>";
|
||||
}
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$("button#test-transport").click(function() {
|
||||
var $this = $(this);
|
||||
var transport_id = $this.data("transport_id");
|
||||
var transport = $this.data("transport");
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'ajax_form.php',
|
||||
data: { type: "test-transport", transport_id: transport_id },
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if (data.status == 'ok') {
|
||||
toastr.success('Test to ' + transport + ' ok');
|
||||
} else {
|
||||
toastr.error('Test to ' + transport + ' failed');
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
toastr.error('Test to ' + transport + ' failed - general error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("[data-toggle='popover']").popover({
|
||||
trigger: 'hover',
|
||||
placement: 'top'
|
||||
});
|
||||
</script>
|
@@ -611,6 +611,7 @@ if ($alerts['active_count'] > 0) {
|
||||
<li><a href="<?php echo(generate_url(array('page'=>'alert-rules'))); ?>"><i class="fa fa-list fa-fw fa-lg" aria-hidden="true"></i> Alert Rules</a></li>
|
||||
<li><a href="<?php echo(generate_url(array('page'=>'alert-schedule'))); ?>"><i class="fa fa-calendar fa-fw fa-lg" aria-hidden="true"></i> Scheduled Maintenance</a></li>
|
||||
<li><a href="<?php echo(generate_url(array('page'=>'templates'))); ?>"><i class="fa fa-file fa-fw fa-lg" aria-hidden="true"></i> Alert Templates</a></li>
|
||||
<li><a href="<?php echo(generate_url(array('page'=>'alert-transports'))); ?>"><i class="fa fa-bus fa-fw fa-lg" aria-hidden="true"></i> Alert Transports</a></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</li>
|
||||
|
3
html/pages/alert-transports.inc.php
Normal file
3
html/pages/alert-transports.inc.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
require_once 'includes/print-alert-transports.php';
|
@@ -398,6 +398,7 @@ $mail_conf = array(
|
||||
);
|
||||
|
||||
echo '
|
||||
<div class="well"><strong>DEPRECATED</strong>: Please use the new Alert Transports section under Alerts to configure transports - <a href="https://docs.librenms.org/Alerting/Transports/" target="_blank">docs</a>.</div>
|
||||
<div class="panel-group" id="accordion">
|
||||
<form class="form-horizontal" role="form" action="" method="post">
|
||||
';
|
||||
@@ -1726,23 +1727,13 @@ echo '
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if (data.status == 'ok') {
|
||||
$this.removeClass('btn-primary').addClass('btn-success');
|
||||
setTimeout(function(){
|
||||
$this.removeClass('btn-success').addClass('btn-primary');
|
||||
}, 2000);
|
||||
}
|
||||
else {
|
||||
$this.removeClass('btn-primary').addClass('btn-danger');
|
||||
setTimeout(function(){
|
||||
$this.removeClass('btn-danger').addClass('btn-primary');
|
||||
}, 2000);
|
||||
toastr.success('Test to ' + transport + ' ok');
|
||||
} else {
|
||||
toastr.error('Test to ' + transport + ' failed');
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
$this.removeClass('btn-primary').addClass('btn-danger');
|
||||
setTimeout(function(){
|
||||
$this.removeClass('btn-danger').addClass('btn-primary');
|
||||
}, 2000);
|
||||
toastr.error('Test to ' + transport + ' failed - general error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -23,8 +23,10 @@
|
||||
*/
|
||||
|
||||
use LibreNMS\Alert\Template;
|
||||
use LibreNMS\Alert\AlertData;
|
||||
use LibreNMS\Alerting\QueryBuilderParser;
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use LibreNMS\Alert\AlertUtil;
|
||||
|
||||
/**
|
||||
* @param $rule
|
||||
@@ -806,39 +808,81 @@ function ExtTransports($obj)
|
||||
global $config;
|
||||
$tmp = false;
|
||||
$type = new Template;
|
||||
// To keep scrutinizer from naging because it doesnt understand eval
|
||||
|
||||
// If alert transport mapping exists, override the default transports
|
||||
$transport_maps = AlertUtil::getAlertTransports($obj['alert_id']);
|
||||
|
||||
if (!$transport_maps) {
|
||||
$transport_maps = AlertUtil::getDefaultAlertTransports();
|
||||
$legacy_transports = AlertUtil::getDefaultTransportList();
|
||||
foreach ($config['alert']['transports'] as $transport => $opts) {
|
||||
if (in_array($transport, $legacy_transports)) {
|
||||
// If it is a default transport type, then the alert has already been sent out, so skip
|
||||
continue;
|
||||
}
|
||||
if (is_array($opts)) {
|
||||
$opts = array_filter($opts);
|
||||
}
|
||||
$class = 'LibreNMS\\Alert\\Transport\\' . ucfirst($transport);
|
||||
if (($opts === true || !empty($opts)) && $opts != false && class_exists($class)) {
|
||||
$obj['transport'] = $transport;
|
||||
$obj['alert'] = collect($obj);
|
||||
$transport_maps[] = [
|
||||
'transport_id' => null,
|
||||
'transport_type' => $transport,
|
||||
'opts' => $opts,
|
||||
'legacy' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
unset($legacy_transports);
|
||||
}
|
||||
|
||||
foreach ($transport_maps as $item) {
|
||||
$class = 'LibreNMS\\Alert\\Transport\\'.ucfirst($item['transport_type']);
|
||||
if (class_exists($class)) {
|
||||
$transport_title = ($item['legacy'] === true) ? "{$item['transport_type']} (legacy)" : $item['transport_type'];
|
||||
$obj['transport'] = $item['transport_type'];
|
||||
$obj['alert'] = new AlertData($obj);
|
||||
$obj['title'] = $type->getTitle($obj);
|
||||
$obj['alert']['title'] = $obj['title'];
|
||||
$obj['msg'] = $type->getBody($obj);
|
||||
echo $transport.' => ';
|
||||
$instance = new $class;
|
||||
$tmp = $instance->deliverAlert($obj, $opts);
|
||||
$prefix = array( 0=>"recovery", 1=>$obj['severity']." alert", 2=>"acknowledgment" );
|
||||
$prefix[3] = &$prefix[0];
|
||||
$prefix[4] = &$prefix[0];
|
||||
if ($tmp === true) {
|
||||
echo 'OK';
|
||||
log_event('Issued ' . $prefix[$obj['state']] . " for rule '" . $obj['name'] . "' to transport '" . $transport . "'", $obj['device_id'], 'alert', 1);
|
||||
} elseif ($tmp === false) {
|
||||
echo 'ERROR';
|
||||
log_event('Could not issue ' . $prefix[$obj['state']] . " for rule '" . $obj['name'] . "' to transport '" . $transport . "'", $obj['device_id'], null, 5);
|
||||
} else {
|
||||
echo "ERROR: $tmp\r\n";
|
||||
log_event('Could not issue ' . $prefix[$obj['state']] . " for rule '" . $obj['name'] . "' to transport '" . $transport . "' Error: " . $tmp, $obj['device_id'], 'error', 5);
|
||||
}
|
||||
echo "$transport_title => ";
|
||||
$instance = new $class($item['transport_id']);
|
||||
$tmp = $instance->deliverAlert($obj, $item['opts']);
|
||||
AlertLog($tmp, $obj, $obj['transport']);
|
||||
unset($instance);
|
||||
echo '; ';
|
||||
}
|
||||
}
|
||||
|
||||
if (count($transport_maps) === 0) {
|
||||
echo 'No configured transports';
|
||||
}
|
||||
}//end ExtTransports()
|
||||
|
||||
// Log alert event
|
||||
function AlertLog($result, $obj, $transport)
|
||||
{
|
||||
$prefix = [
|
||||
0 => "recovery",
|
||||
1 => $obj['severity']." alert",
|
||||
2 => "acknowledgment"
|
||||
];
|
||||
$prefix[3] = &$prefix[0];
|
||||
$prefix[4] = &$prefix[0];
|
||||
if ($result === true) {
|
||||
echo 'OK';
|
||||
log_event('Issued ' . $prefix[$obj['state']] . " for rule '" . $obj['name'] . "' to transport '" . $transport . "'", $obj['device_id'], 'alert', 1);
|
||||
} elseif ($result === false) {
|
||||
echo 'ERROR';
|
||||
log_event('Could not issue ' . $prefix[$obj['state']] . " for rule '" . $obj['name'] . "' to transport '" . $transport . "'", $obj['device_id'], null, 5);
|
||||
} else {
|
||||
echo "ERROR: $result\r\n";
|
||||
log_event('Could not issue ' . $prefix[$obj['state']] . " for rule '" . $obj['name'] . "' to transport '" . $transport . "' Error: " . $result, $obj['device_id'], 'error', 5);
|
||||
}
|
||||
return;
|
||||
}//end AlertLog()
|
||||
|
||||
|
||||
/**
|
||||
* Check if a device's all parent are down
|
||||
* Returns true if all parents are down
|
||||
|
@@ -117,6 +117,29 @@ alert_template_map:
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
|
||||
alert_templates_id: { Name: alert_templates_id, Columns: [alert_templates_id, alert_rule_id], Unique: false, Type: BTREE }
|
||||
alert_transports:
|
||||
Columns:
|
||||
- { Field: transport_id, Type: int(11), 'Null': false, Extra: auto_increment }
|
||||
- { Field: transport_name, Type: varchar(30), 'Null': false, Extra: '' }
|
||||
- { Field: transport_type, Type: varchar(20), 'Null': false, Extra: '', Default: mail }
|
||||
- { Field: is_default, Type: tinyint(1), 'Null': false, Extra: '', Default: '0' }
|
||||
- { Field: transport_config, Type: text, 'Null': true, Extra: '' }
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [transport_id], Unique: true, Type: BTREE }
|
||||
alert_transport_groups:
|
||||
Columns:
|
||||
- { Field: transport_group_id, Type: int(11), 'Null': false, Extra: auto_increment }
|
||||
- { Field: transport_group_name, Type: varchar(30), 'Null': false, Extra: '' }
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [transport_group_id], Unique: true, Type: BTREE }
|
||||
alert_transport_map:
|
||||
Columns:
|
||||
- { Field: id, Type: int(11), 'Null': false, Extra: auto_increment }
|
||||
- { Field: rule_id, Type: int(11), 'Null': false, Extra: '' }
|
||||
- { Field: transport_or_group_id, Type: int(11), 'Null': false, Extra: '' }
|
||||
- { Field: target_type, Type: varchar(16), 'Null': false, Extra: '' }
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
|
||||
api_tokens:
|
||||
Columns:
|
||||
- { Field: id, Type: int(11), 'Null': false, Extra: auto_increment }
|
||||
@@ -1566,6 +1589,10 @@ toner:
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [toner_id], Unique: true, Type: BTREE }
|
||||
device_id: { Name: device_id, Columns: [device_id], Unique: false, Type: BTREE }
|
||||
transport_group_transport:
|
||||
Columns:
|
||||
- { Field: transport_group_id, Type: int(11), 'Null': false, Extra: '' }
|
||||
- { Field: transport_id, Type: int(11), 'Null': false, Extra: '' }
|
||||
ucd_diskio:
|
||||
Columns:
|
||||
- { Field: diskio_id, Type: int(11), 'Null': false, Extra: auto_increment }
|
||||
|
@@ -105,6 +105,7 @@ pages:
|
||||
- Alerting/Rules.md
|
||||
- Alerting/Templates.md
|
||||
- Alerting/Transports.md
|
||||
- Alerting/Creating-Transport.md
|
||||
- Alerting/Entities.md
|
||||
- Alerting/Macros.md
|
||||
- Alerting/Testing.md
|
||||
|
4
sql-schema/255.sql
Normal file
4
sql-schema/255.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
CREATE TABLE IF NOT EXISTS alert_transports (transport_id INT(11) NOT NULL AUTO_INCREMENT, transport_name VARCHAR(30) NOT NULL COLLATE utf8_unicode_ci, transport_type VARCHAR(20) NOT NULL DEFAULT 'mail', is_default BOOL NOT NULL DEFAULT false, transport_config TEXT, PRIMARY KEY(transport_id));
|
||||
CREATE TABLE IF NOT EXISTS alert_transport_map (id INT(11) NOT NULL AUTO_INCREMENT, rule_id INT(11) NOT NULL, transport_or_group_id INT(11) NOT NULL, target_type VARCHAR(16) NOT NULL, PRIMARY KEY(id));
|
||||
CREATE TABLE IF NOT EXISTS alert_transport_groups (transport_group_id INT(11) NOT NULL AUTO_INCREMENT, transport_group_name VARCHAR(30) NOT NULL COLLATE utf8_unicode_ci, PRIMARY KEY(transport_group_id));
|
||||
CREATE TABLE IF NOT EXISTS transport_group_transport (transport_group_id INT(11) NOT NULL, transport_id INT(11) NOT NULL);
|
@@ -25,6 +25,11 @@
|
||||
|
||||
namespace LibreNMS\Tests;
|
||||
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use RecursiveRegexIterator;
|
||||
use RegexIterator;
|
||||
|
||||
class AlertTest extends TestCase
|
||||
{
|
||||
public function testJsonAlertCollection()
|
||||
@@ -35,4 +40,29 @@ class AlertTest extends TestCase
|
||||
$this->assertInternalType('array', $rule);
|
||||
}
|
||||
}
|
||||
|
||||
public function testTransports()
|
||||
{
|
||||
foreach ($this->getTransportFiles() as $file => $_unused) {
|
||||
$parts = explode('/', $file);
|
||||
$transport = ucfirst(str_replace('.php', '', array_pop($parts)));
|
||||
$class = 'LibreNMS\\Alert\\Transport\\'.$transport;
|
||||
if (!class_exists($class)) {
|
||||
$this->assertTrue(false, "The transport $transport does not exist");
|
||||
} else {
|
||||
$methods = ['deliverAlert', 'configTemplate', 'contact'.$transport];
|
||||
foreach ($methods as $method) {
|
||||
if (!method_exists($class, $method)) {
|
||||
$this->assertTrue(false, "The transport $transport does not have the method $method");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getTransportFiles()
|
||||
{
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('LibreNMS/Alert/Transport'));
|
||||
return new RegexIterator($iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user