From 5b57e75b2e90c899efd94fac575cbed7c8324354 Mon Sep 17 00:00:00 2001 From: laf Date: Mon, 25 May 2015 21:51:27 +0100 Subject: [PATCH] Final work getting alerts dynconfig done --- alerts.php | 2 +- doc/Extensions/Alerting.md | 14 + doc/Support/Configuration.md | 2 + html/forms/config-item.inc.php | 108 +++++ html/forms/update-config-item.inc.php | 31 +- html/includes/functions.inc.php | 11 +- html/pages/settings.inc.php | 237 +---------- html/pages/settings/alerting.inc.php | 567 +++++++++++++++++++++++++- includes/definitions.inc.php | 44 +- 9 files changed, 751 insertions(+), 265 deletions(-) create mode 100644 html/forms/config-item.inc.php diff --git a/alerts.php b/alerts.php index 6af7370b3..83194849c 100755 --- a/alerts.php +++ b/alerts.php @@ -247,7 +247,7 @@ function ExtTransports($obj) { global $config; $tmp = false; //To keep scrutinizer from naging because it doesnt understand eval foreach( $config['alert']['transports'] as $transport=>$opts ) { - if( ($opts === true || !empty($opts)) && file_exists($config['install_dir']."/includes/alerts/transport.".$transport.".php") ) { + if( ($opts === true || !empty($opts)) && $opts != false && file_exists($config['install_dir']."/includes/alerts/transport.".$transport.".php") ) { echo $transport." => "; eval('$tmp = function($obj,$opts) { global $config; '.file_get_contents($config['install_dir']."/includes/alerts/transport.".$transport.".php").' };'); $tmp = $tmp($obj,$opts); diff --git a/doc/Extensions/Alerting.md b/doc/Extensions/Alerting.md index 59fb295f9..7448a279c 100644 --- a/doc/Extensions/Alerting.md +++ b/doc/Extensions/Alerting.md @@ -138,6 +138,8 @@ $config['alert']['admins'] = true; //Include Adminstrators into alert-contacts ## E-Mail +> You can configure these options within the WebUI now, please avoid setting these options within config.php + E-Mail transport is enabled with adding the following to your `config.php`: ```php $config['alert']['transports']['mail'] = true; @@ -164,6 +166,8 @@ $config['alert']['default_mail'] = ''; //Default ema ## 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. @@ -179,6 +183,8 @@ $config['alert']['transports']['api']['get'][] = "https://api.thirdparti.es/issu ## 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 @@ -187,6 +193,8 @@ $config['alert']['transports']['nagios'] = "/path/to/my.fifo"; //Flapjack expect ## 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 @@ -195,6 +203,8 @@ $config['alert']['transports']['irc'] = true; ## Slack +> You can configure these options within the WebUI now, please avoid setting these options within config.php + The Slack transport will POST the alert message to your Slack Incoming WebHook, you are able to specify multiple webhooks along with the relevant options to go with it. 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: ```php @@ -206,6 +216,8 @@ $config['alert']['transports']['slack'][] = array('url' => "https://hooks.slack. ## HipChat +> You can configure these options within the WebUI now, please avoid setting these options within config.php + The HipChat transport requires the following: __room_id__ = HipChat Room ID @@ -251,6 +263,8 @@ $config['alert']['transports']['hipchat'][] = array("url" => "https://api.hipcha ## PagerDuty +> You can configure these options within the WebUI now, please avoid setting these options within config.php + 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. diff --git a/doc/Support/Configuration.md b/doc/Support/Configuration.md index 4ef27c2c0..79b24e91b 100644 --- a/doc/Support/Configuration.md +++ b/doc/Support/Configuration.md @@ -211,6 +211,8 @@ Arrays of subnets to exclude in auto discovery mode. #### Email configuration +> You can configure these options within the WebUI now, please avoid setting these options within config.php + ```php $config['email_backend'] = 'mail'; $config['email_from'] = NULL; diff --git a/html/forms/config-item.inc.php b/html/forms/config-item.inc.php new file mode 100644 index 000000000..1a481b64a --- /dev/null +++ b/html/forms/config-item.inc.php @@ -0,0 +1,108 @@ + + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. Please see LICENSE.txt at the top level of + * the source code distribution for details. + */ + +if(is_admin() === false) { + $response = array('status'=>'error','message'=>'Need to be admin'); + echo _json_encode($response); + exit; +} + +$action = mres($_POST['action']); +$config_group = mres($_POST['config_group']); +$config_sub_group = mres($_POST['config_sub_group']); +$config_name = mres($_POST['config_name']); +$config_value = mres($_POST['config_value']); +$config_extra = mres($_POST['config_extra']); +$config_room_id = mres($_POST['config_room_id']); +$config_from = mres($_POST['config_from']); +$status = 'error'; +$message = 'Error with config'; + +if ($action == 'remove' || $action == 'remove-slack' || $action == 'remove-hipchat') { + $config_id = mres($_POST['config_id']); + if (empty($config_id)) { + $message = 'No config id passed'; + } else { + if (dbDelete('config', '`config_id`=?', array($config_id))) { + if ($action == 'remove-slack') { + dbDelete('config', "`config_name` LIKE 'alert.transports.slack.$config_id.%'"); + } elseif ($action == 'remove-hipchat') { + dbDelete('config', "`config_name` LIKE 'alert.transports.hipchat.$config_id.%'"); + } + $status = 'ok'; + $message = 'Config item removed'; + } else { + $message = 'General error, could not remove config'; + } + } +} elseif ($action == 'add-slack') { + if (empty($config_value)) { + $message = 'No Slack url provided'; + } else { + $config_id = dbInsert(array('config_name' => 'alert.transports.slack.', 'config_value' => $config_value, 'config_group' => $config_group, 'config_sub_group' => $config_sub_group, 'config_default'=>$config_value, 'config_descr'=>'Slack Transport'), 'config'); + if ($config_id > 0) { + dbUpdate(array('config_name' => 'alert.transports.slack.'.$config_id.'.url'), 'config', 'config_id=?', array($config_id)); + $status = 'ok'; + $message = 'Config item created'; + $extras = explode('\n',$config_extra); + foreach ($extras as $option) { + list($k,$v) = explode("=", $option,2); + if (!empty($k) || !empty($v)) { + dbInsert(array('config_name' => 'alert.transports.slack.'.$config_id.'.'.$k, 'config_value' => $v, 'config_group' => $config_group, 'config_sub_group' => $config_sub_group, 'config_default'=>$v, 'config_descr'=>'Slack Transport'), 'config'); + } + } + } else { + $message = 'Could not create config item'; + } + } +} elseif ($action == 'add-hipchat') { + if (empty($config_value) || empty($config_room_id) || empty($config_from)) { + $message = 'No hipchat url, room id or from provided'; + } else { + $config_id = dbInsert(array('config_name' => 'alert.transports.hipchat.', 'config_value' => $config_value, 'config_group' => $config_group, 'config_sub_group' => $config_sub_group, 'config_default'=>$config_value, 'config_descr'=>'Hipchat Transport'), 'config'); + if ($config_id > 0) { + dbUpdate(array('config_name' => 'alert.transports.hipchat.'.$config_id.'.url'), 'config', 'config_id=?', array($config_id)); + dbInsert(array('config_name' => 'alert.transports.hipchat.'.$config_id.'.room_id', 'config_value' => $config_room_id, 'config_group' => $config_group, 'config_sub_group' => $config_sub_group, 'config_default'=>$config_room_id, 'config_descr'=>'Hipchat URL'), 'config'); + dbInsert(array('config_name' => 'alert.transports.hipchat.'.$config_id.'.from', 'config_value' => $config_from, 'config_group' => $config_group, 'config_sub_group' => $config_sub_group, 'config_default'=>$config_from, 'config_descr'=>'Hipchat From'), 'config'); + $status = 'ok'; + $message = 'Config item created'; + $extras = explode('\n',$config_extra); + foreach ($extras as $option) { + list($k,$v) = explode("=", $option,2); + if (!empty($k) || !empty($v)) { + dbInsert(array('config_name' => 'alert.transports.hipchat.'.$config_id.'.'.$k, 'config_value' => $v, 'config_group' => $config_group, 'config_sub_group' => $config_sub_group, 'config_default'=>$v, 'config_descr'=>'Hipchat '.$v), 'config'); + } + } + } else { + $message = 'Could not create config item'; + } + } +} else { + + if (empty($config_group) || empty($config_sub_group) || empty($config_name) || empty($config_value)) { + $message = 'Missing config name or value'; + } else { + $config_id = dbInsert(array('config_name' => $config_name, 'config_value' => $config_value, 'config_group' => $config_group, 'config_sub_group' => $config_sub_group, 'config_default'=>$config_value, 'config_descr'=>'API Transport'), 'config'); + if ($config_id > 0) { + dbUpdate(array('config_name'=>$config_name.$config_id),'config','config_id=?',array($config_id)); + $status = 'ok'; + $message = 'Config item created'; + } else { + $message = 'Could not create config item'; + } + } +} + +$response = array('status'=>$status,'message'=>$message, 'config_id'=>$config_id); +echo _json_encode($response); diff --git a/html/forms/update-config-item.inc.php b/html/forms/update-config-item.inc.php index b7604a325..4c8cc5545 100644 --- a/html/forms/update-config-item.inc.php +++ b/html/forms/update-config-item.inc.php @@ -16,14 +16,39 @@ if(is_admin() === false) { die('ERROR: You need to be admin'); } +$config_id = mres($_POST['config_id']); +$action = mres($_POST['action']); +$config_type = mres($_POST['config_type']); + $status = 'error'; -if (!is_numeric($_POST['config_id'])) { +if (!is_numeric($config_id)) { $message = 'ERROR: No alert selected'; - exit; +} elseif ($action == 'update-textarea') { + $extras = explode(PHP_EOL,$_POST['config_value']); + foreach ($extras as $option) { + list($k,$v) = explode("=", $option,2); + if (!empty($k) || !empty($v)) { + if ($config_type == 'slack') { + $db_id[] = dbInsert(array('config_name' => 'alert.transports.slack.'.$config_id.'.'.$k, 'config_value' => $v, 'config_group' => 'alerting', 'config_sub_group' => 'transports', 'config_default'=>$v, 'config_descr'=>'Slack Transport'), 'config'); + } elseif ($config_type == 'hipchat') { + $db_id[] = dbInsert(array('config_name' => 'alert.transports.hipchat.'.$config_id.'.'.$k, 'config_value' => $v, 'config_group' => 'alerting', 'config_sub_group' => 'transports', 'config_default'=>$v, 'config_descr'=>'Hipchat Transport'), 'config'); + } + } + } + $db_inserts = implode(",",$db_id); + if (!empty($db_inserts)) { + if ($config_type == 'slack') { + dbDelete('config',"(`config_name` LIKE 'alert.transports.slack.$config_id.%' AND `config_name` != 'alert.transports.slack.$config_id.url' AND `config_id` NOT IN ($db_inserts))"); + } elseif ($config_type == 'hipchat') { + dbDelete('config',"(`config_name` LIKE 'alert.transports.hipchat.$config_id.%' AND (`config_name` != 'alert.transports.hipchat.$config_id.url' AND `config_name` != 'alert.transports.hipchat.$config_id.room_id' AND `config_name` != 'alert.transports.hipchat.$config_id.from') AND `config_id` NOT IN ($db_inserts))"); + } + } + $message = 'Config item has been updated:'; + $status = 'ok'; } else { $state = mres($_POST['config_value']); - $update = dbUpdate(array('config_value' => $state), 'config', '`config_id`=?', array($_POST['config_id'])); + $update = dbUpdate(array('config_value' => $state), 'config', '`config_id`=?', array($config_id)); if(!empty($update) || $update == '0') { $message = 'Alert rule has been updated.'; diff --git a/html/includes/functions.inc.php b/html/includes/functions.inc.php index 65772e2e3..d846d2ce8 100644 --- a/html/includes/functions.inc.php +++ b/html/includes/functions.inc.php @@ -805,14 +805,19 @@ function get_config_by_group($group) { return $items; } -function get_config_by_name($name) { +function get_config_like_name($name) { $name = array($name); - foreach (dbFetchRows("SELECT * FROM `config` WHERE `config_name` = '?'", array($name)) as $config_item) { - $items[] = $config_item; + foreach (dbFetchRows("SELECT * FROM `config` WHERE `config_name` LIKE '%?%'", array($name)) as $config_item) { + $items[$config_item['config_name']] = $config_item; } return $items; } +function get_config_by_name($name) { + $config_item = dbFetchRow("SELECT * FROM `config` WHERE `config_name` = ?", array($name)); + return $config_item; +} + function set_config_name($name,$config_value) { return dbUpdate(array('config_value' => $config_value), 'config', '`config_name`=?', array($name)); } diff --git a/html/pages/settings.inc.php b/html/pages/settings.inc.php index 3dac71da6..cb2d3ca94 100644 --- a/html/pages/settings.inc.php +++ b/html/pages/settings.inc.php @@ -54,14 +54,14 @@ foreach (dbFetchRows("SELECT `config_group` FROM `config` GROUP BY `config_group $sub_page = $sub_page['config_group']; ?>
- + Settings
- +
= 10 ) { include("includes/error-no-perm.inc.php"); } -if ($_SESSION['userlevel'] >= '10') { + if ($_SESSION['userlevel'] >= '10') { -?> - - - - -
- -
- -
-
-

System Settings

-
-
- -
-
-
-
-'); - - foreach (dbFetchRows("SELECT config_id,config_group FROM `config` WHERE config_hidden='0' GROUP BY config_group ORDER BY config_group ASC ,config_group_order DESC") as $group) - { - $grp_num = $group['config_group_order']; - $grp_title = $group['config_group']; - $found++; - echo(' -
- -
-
-'); - foreach (dbFetchRows("SELECT * FROM `config` WHERE config_group='".$group['config_group']."' ORDER BY config_sub_group ASC, config_sub_group_order DESC, config_name ASC") as $cfg) - { - $cfg_ids[] = $cfg['config_id']; - $cfg_disabled = ''; - if($cfg['config_disabled'] == '1') - { - $cfg_disabled = 'checked'; - } - echo(' -
- -
- -
-
-
- -
-
- -
-
-'); - - } - - echo(' -
-
-
-'); - - } - - - echo(' - -'); - - if ($debug) - { - echo("
");
-    print_r($config);
-    echo("
"); - } - -?> - - - - - + + + + + + + + + + + + + +
-
+
- + +
+
+
+ +
+
+
@@ -79,6 +188,13 @@ echo '
+
+ +
+
+ +
+
@@ -92,9 +208,9 @@ echo '
-
+
- +
@@ -215,7 +331,32 @@ echo '
- + +
+
'; + $api_urls = get_config_like_name('alert.transports.api.%.'); + foreach ($api_urls as $api_url) { + $api_split = split("\.", $api_url['config_name']); + $api_method = $api_split[3]; + echo '
+ +
+ + +
+
+ +
+
'; + } + echo '
+ +
+ + +
+
+
@@ -235,7 +376,7 @@ echo '
'; if (empty($config_groups['alert.transports.pagerduty']['config_value']) === FALSE) { - echo "". $config_groups['alert.transports.pagerduty']['config_value']; + echo ""; } else { echo ""; } @@ -244,6 +385,201 @@ echo '
+
+ +
+
+
+ +
+
+ + +
+
+
+
+
+
+
+

+ IRC transport +

+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+

+ Slack transport +

+
+
+
+
+
+ +
+
'; + $slack_urls = get_config_like_name('alert.transports.slack.%.url'); + foreach ($slack_urls as $slack_url) { + unset($upd_slack_extra); + $new_slack_extra = array(); + $slack_extras = get_config_like_name('alert.transports.slack.'.$slack_url['config_id'].'.%'); + foreach ($slack_extras as $extra) { + $split_extra = explode('.',$extra['config_name']); + if ($split_extra[4] != 'url') { + $new_slack_extra[] = $split_extra[4] . '=' . $extra['config_value']; + } + } + $upd_slack_extra = implode(PHP_EOL,$new_slack_extra); + echo '
+
+ +
+ + +
+
+ +
+
+
+
+ + +
+
+
'; + } + echo '
+
+ +
+ + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ +
+
'; + $hipchat_urls = get_config_like_name('alert.transports.hipchat.%.url'); + foreach ($hipchat_urls as $hipchat_url) { + unset($upd_hipchat_extra); + $new_hipchat_extra = array(); + $hipchat_extras = get_config_like_name('alert.transports.hipchat.'.$hipchat_url['config_id'].'.%'); + $hipchat_room_id = get_config_by_name('alert.transports.hipchat.'.$hipchat_url['config_id'].'.room_id'); + $hipchat_from = get_config_by_name('alert.transports.hipchat.'.$hipchat_url['config_id'].'.from'); + foreach ($hipchat_extras as $extra) { + $split_extra = explode('.',$extra['config_name']); + if ($split_extra[4] != 'url' && $split_extra[4] != 'room_id' && $split_extra[4] != 'from') { + $new_hipchat_extra[] = $split_extra[4] . '=' . $extra['config_value']; + } + } + $upd_hipchat_extra = implode(PHP_EOL,$new_hipchat_extra); + echo '
+
+ +
+ + +
+
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ + +
+
+
'; + } + echo '
+
+ +
+ + +
+
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+
+
+
+
+
'; @@ -252,8 +588,192 @@ echo ' diff --git a/includes/definitions.inc.php b/includes/definitions.inc.php index c8029c51f..ea8dd65c6 100644 --- a/includes/definitions.inc.php +++ b/includes/definitions.inc.php @@ -14,32 +14,34 @@ if (!$database_link) $database_db = mysql_select_db($config['db_name'], $database_link); function mergecnf($obj) { - $pointer = array(); - $val = $obj['config_value']; - $obj = $obj['config_name']; - $obj = explode('.',$obj,2); - if (!isset($obj[1])) { - if (filter_var($val,FILTER_VALIDATE_INT)) { - $val = (int) $val; - } elseif (filter_var($val,FILTER_VALIDATE_FLOAT)) { - $val = (float) $val; - } elseif (filter_var($val,FILTER_VALIDATE_BOOLEAN)) { - $val =(boolean) $val; - } - if (!empty($obj[0])) { - return array($obj[0] => $val); - } else { - return array($val); - } - } else { - $pointer[$obj[0]] = mergecnf(array('config_name'=>$obj[1],'config_value'=>$val)); + $pointer = array(); + $val = $obj['config_value']; + $obj = $obj['config_name']; + $obj = explode('.',$obj,2); + if( !isset($obj[1]) ) { + if( filter_var($val,FILTER_VALIDATE_INT) ) { + $val = (int) $val; + } elseif( filter_var($val,FILTER_VALIDATE_FLOAT) ) { + $val = (float) $val; + } elseif( filter_var($val,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE) !== NULL ) { + $val = filter_var($val,FILTER_VALIDATE_BOOLEAN); } - return $pointer; + if( !empty($obj[0]) ) { + return array($obj[0] => $val); + } else { + return array($val); + } + } else { + $pointer[$obj[0]] = mergecnf(array('config_name'=>$obj[1],'config_value'=>$val)); + } + return $pointer; } +$clone = $config; foreach( dbFetchRows('select config_name,config_value from config') as $obj ) { - $config = array_merge_recursive($config,mergecnf($obj)); + $clone = array_replace_recursive($clone,mergecnf($obj)); } +$config = array_replace_recursive($clone,$config); ///////////////////////////////////////////////////////// # NO CHANGES TO THIS FILE, IT IS NOT USER-EDITABLE #