mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
* feature: Added new alert rule builder UI * Updated to export sql queries * More updates * more changes * removed debug * fix scrut * Updated to include import options + various other fixes * fix rule * Populate name from collection rules. * Fix default rule import Allow new and old style rules in the collection. Don't add new yet as I'm not sure GenSQL() is working. * Fix GenSQL call * Extract filter building to class so it is nicely contained in one place * moved schema * some fixes and tweaks * travis fixes * Some more features / updates * Fix up my mistakes when adding default rules * Use a modal for new alert (Incomplete) Larger dialog!! Remove page loading stuff. Working: Loading rules, resetting dialog, importing from collection. Not working yet: select width device limited rule access? don't know what this is... Lots of unused stuff to delete... * reload "table" after save * fixed editing rule * Auto select2 width * Reload window on save * Restore per-device alert. Remove debug. * Small cleanups. Rule Name first. * Restore button to button type. Rename schema. * Fixes: wrong command to reload window, remove extra attributes, rule is never passed * Fixed old rule editing * some small updates for old imports * travis update to use trusty * maybe travis fix * Ability to set alert rule mappings on the rule edit screen * pip installs one line, no quiet for deploy * update schema def * Fix style and some copyright headers * fix docs missing file * Allow new versions of snmpsim and libraries * Parser WIP * Fix default rules insert * reorganize * Legacy import first draft done * Implement saving Skip translation to sql for now * Working on glues * small rule collection fix * Working on glues * Working on glues * Docs updates + small UI changes * Parser WIP * reorganize * Legacy import first draft done * Implement saving Skip translation to sql for now * Working on glues * Working on glues * Working on glues * Add table mapping, should move to it's own class * WIP * Glue working!! * Extract Schema class * Some final touches. revert alerts_rules.json for now. * Finish up initial implementation Needs more tests * Fix a few places * small doc updates * Fix finding tables in grouped rules. * remove unused code * code format fixes * Some quick tests for Schema Simplified output for findRelationshipPath. Always includes start and target in the result. This simplifies a lot of code in QueryBuilderParser.php This also always loads the target table data now (which we want) * Make bill_id the PRIMARY index for the bills table * Load macros from a json file in misc instead of the database. * Fix whitespace and wrong key for collection. * Handle IN properly when generating SQL * Fix glue (devices.device_id = ports.port_id) is incorrect :D Show ALL tables we can resolve relationships for in the query builder filter. * Remove all macros from the database Remove insert statements, leave updates to update user's existing rules.
392 lines
12 KiB
PHP
392 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Config.php
|
|
*
|
|
* Config convenience class to access and set config variables.
|
|
*
|
|
* 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 2017 Tony Murray
|
|
* @author Tony Murray <murraytony@gmail.com>
|
|
*/
|
|
|
|
namespace LibreNMS;
|
|
|
|
class Config
|
|
{
|
|
/**
|
|
* Load the user config from config.php
|
|
*
|
|
* @param string $install_dir
|
|
* @return array
|
|
*/
|
|
public static function &load($install_dir = null)
|
|
{
|
|
global $config;
|
|
|
|
if (empty($install_dir)) {
|
|
$install_dir = __DIR__ . '/../';
|
|
}
|
|
$install_dir = realpath($install_dir);
|
|
$config['install_dir'] = $install_dir;
|
|
|
|
// load defaults
|
|
require $install_dir . '/includes/defaults.inc.php';
|
|
require $install_dir . '/includes/definitions.inc.php';
|
|
|
|
// import standard settings
|
|
$macros = json_decode(file_get_contents($install_dir . '/misc/macros.json'), true);
|
|
self::set('alert.macros.rule', $macros);
|
|
|
|
// variable definitions (remove me)
|
|
require $install_dir . '/includes/vmware_guestid.inc.php';
|
|
|
|
// Load user config
|
|
include $install_dir . '/config.php';
|
|
|
|
return $config;
|
|
}
|
|
|
|
/**
|
|
* Load Config from the database
|
|
*
|
|
* @throws Exceptions\DatabaseConnectException
|
|
*/
|
|
public static function &loadFromDatabase()
|
|
{
|
|
global $config;
|
|
|
|
if (empty($config)) {
|
|
self::load();
|
|
}
|
|
|
|
// Make sure the database is connected
|
|
dbConnect();
|
|
|
|
// pull in the database config settings
|
|
self::mergeDb();
|
|
|
|
// load graph types from the database
|
|
self::loadGraphsFromDb();
|
|
|
|
// Process $config to tidy up
|
|
self::processConfig();
|
|
|
|
return $config;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a config value, if non existent null (or default if set) will be returned
|
|
*
|
|
* @param string $key period separated config variable name
|
|
* @param mixed $default optional value to return if the setting is not set
|
|
* @return mixed
|
|
*/
|
|
public static function get($key, $default = null)
|
|
{
|
|
global $config;
|
|
|
|
if (isset($config[$key])) {
|
|
return $config[$key];
|
|
}
|
|
|
|
if (!str_contains($key, '.')) {
|
|
return $default;
|
|
}
|
|
|
|
$keys = explode('.', $key);
|
|
|
|
$curr = &$config;
|
|
foreach ($keys as $k) {
|
|
// do not add keys that don't exist
|
|
if (!isset($curr[$k])) {
|
|
return $default;
|
|
}
|
|
$curr = &$curr[$k];
|
|
}
|
|
|
|
if (is_null($curr)) {
|
|
return $default;
|
|
}
|
|
|
|
return $curr;
|
|
}
|
|
|
|
/**
|
|
* Get a setting from a device, if that is not set,
|
|
* fall back to the global config setting prefixed by $global_prefix
|
|
* The key must be the same for the global setting and the device setting.
|
|
*
|
|
* @param array $device Device array
|
|
* @param string $key Name of setting to fetch
|
|
* @param string $global_prefix specify where the global setting lives in the global config
|
|
* @param mixed $default will be returned if the setting is not set on the device or globally
|
|
* @return mixed
|
|
*/
|
|
public static function getDeviceSetting($device, $key, $global_prefix = null, $default = null)
|
|
{
|
|
if (isset($device[$key])) {
|
|
return $device[$key];
|
|
}
|
|
|
|
if (isset($global_prefix)) {
|
|
$key = "$global_prefix.$key";
|
|
}
|
|
|
|
return self::get($key, $default);
|
|
}
|
|
|
|
/**
|
|
* Get a setting from the $config['os'] array using the os of the given device
|
|
* If that is not set, fallback to the same global config key
|
|
*
|
|
* @param string $os The os name
|
|
* @param string $key period separated config variable name
|
|
* @param mixed $default optional value to return if the setting is not set
|
|
* @return mixed
|
|
*/
|
|
public static function getOsSetting($os, $key, $default = null)
|
|
{
|
|
global $config;
|
|
|
|
if ($os) {
|
|
if (isset($config['os'][$os][$key])) {
|
|
return $config['os'][$os][$key];
|
|
}
|
|
|
|
if (!str_contains($key, '.')) {
|
|
return self::get($key, $default);
|
|
}
|
|
|
|
$os_key = "os.$os.$key";
|
|
if (self::has($os_key)) {
|
|
return self::get($os_key);
|
|
}
|
|
}
|
|
|
|
return self::get($key, $default);
|
|
}
|
|
|
|
/**
|
|
* Get the merged array from the global and os settings for the specified key.
|
|
* Removes any duplicates.
|
|
* When the arrays have keys, os settings take precedence over global settings
|
|
*
|
|
* @param string $os The os name
|
|
* @param string $key period separated config variable name
|
|
* @param array $default optional array to return if the setting is not set
|
|
* @return array
|
|
*/
|
|
public static function getCombined($os, $key, $default = array())
|
|
{
|
|
global $config;
|
|
|
|
if (!self::has($key)) {
|
|
return self::get("os.$os.$key", $default);
|
|
}
|
|
|
|
if (!isset($config['os'][$os][$key])) {
|
|
if (!str_contains($key, '.')) {
|
|
return self::get($key, $default);
|
|
}
|
|
if (!self::has("os.$os.$key")) {
|
|
return self::get($key, $default);
|
|
}
|
|
}
|
|
|
|
return array_unique(array_merge(
|
|
(array)self::get($key, $default),
|
|
(array)self::getOsSetting($os, $key, $default)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Set a variable in the global config
|
|
*
|
|
* @param mixed $key period separated config variable name
|
|
* @param mixed $value
|
|
* @param bool $persist set the setting in the database so it persists across runs
|
|
* @param string $default default (only set when initially created)
|
|
* @param string $descr webui description (only set when initially created)
|
|
* @param string $group webui group (only set when initially created)
|
|
* @param string $sub_group webui subgroup (only set when initially created)
|
|
*/
|
|
public static function set($key, $value, $persist = false, $default = '', $descr = '', $group = '', $sub_group = '')
|
|
{
|
|
global $config;
|
|
|
|
if ($persist) {
|
|
$res = dbUpdate(array('config_value' => $value), 'config', '`config_name`=?', array($key));
|
|
if (!$res && !dbFetchCell('SELECT 1 FROM `config` WHERE `config_name`=?', array($key))) {
|
|
$insert = array(
|
|
'config_name' => $key,
|
|
'config_value' => $value,
|
|
'config_default' => $default,
|
|
'config_descr' => $descr,
|
|
'config_group' => $group,
|
|
'config_sub_group' => $sub_group,
|
|
);
|
|
dbInsert($insert, 'config');
|
|
}
|
|
}
|
|
|
|
$keys = explode('.', $key);
|
|
|
|
$curr = &$config;
|
|
foreach ($keys as $k) {
|
|
$curr = &$curr[$k];
|
|
}
|
|
|
|
$curr = $value;
|
|
}
|
|
|
|
/**
|
|
* Check if a setting is set
|
|
*
|
|
* @param string $key period separated config variable name
|
|
* @return bool
|
|
*/
|
|
public static function has($key)
|
|
{
|
|
global $config;
|
|
|
|
if (isset($config[$key])) {
|
|
return true;
|
|
}
|
|
|
|
if (!str_contains($key, '.')) {
|
|
return false;
|
|
}
|
|
|
|
$keys = explode('.', $key);
|
|
$last = array_pop($keys);
|
|
|
|
$curr = &$config;
|
|
foreach ($keys as $k) {
|
|
// do not add keys that don't exist
|
|
if (!isset($curr[$k])) {
|
|
return false;
|
|
}
|
|
$curr = &$curr[$k];
|
|
}
|
|
|
|
return is_array($curr) && isset($curr[$last]);
|
|
}
|
|
|
|
/**
|
|
* merge the database config with the global config
|
|
* Global config overrides db
|
|
*/
|
|
private static function mergeDb()
|
|
{
|
|
global $config;
|
|
|
|
$db_config = array();
|
|
foreach (dbFetchRows('SELECT `config_name`,`config_value` FROM `config`') as $obj) {
|
|
self::assignArrayByPath($db_config, $obj['config_name'], $obj['config_value']);
|
|
}
|
|
$config = array_replace_recursive($db_config, $config);
|
|
}
|
|
|
|
/**
|
|
* Assign a value into the passed array by a path
|
|
* 'snmp.version' = 'v1' becomes $arr['snmp']['version'] = 'v1'
|
|
*
|
|
* @param array $arr the array to insert the value into, will be modified in place
|
|
* @param string $path the path to insert the value at
|
|
* @param mixed $value the value to insert, will be type cast
|
|
* @param string $separator path separator
|
|
*/
|
|
private static function assignArrayByPath(&$arr, $path, $value, $separator = '.')
|
|
{
|
|
// type cast value. Is this needed here?
|
|
if (filter_var($value, FILTER_VALIDATE_INT)) {
|
|
$value = (int) $value;
|
|
} elseif (filter_var($value, FILTER_VALIDATE_FLOAT)) {
|
|
$value = (float) $value;
|
|
} elseif (filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null) {
|
|
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
|
}
|
|
|
|
$keys = explode($separator, $path);
|
|
|
|
// walk the array creating keys if they don't exist
|
|
foreach ($keys as $key) {
|
|
$arr = &$arr[$key];
|
|
}
|
|
// assign the variable
|
|
$arr = $value;
|
|
}
|
|
|
|
private static function loadGraphsFromDb()
|
|
{
|
|
global $config;
|
|
|
|
// load graph types from the database
|
|
foreach (dbFetchRows('SELECT * FROM graph_types') as $graph) {
|
|
foreach ($graph as $k => $v) {
|
|
if (strpos($k, 'graph_') == 0) {
|
|
// remove leading 'graph_' from column name
|
|
$key = str_replace('graph_', '', $k);
|
|
} else {
|
|
$key = $k;
|
|
}
|
|
$g[$key] = $v;
|
|
}
|
|
|
|
$config['graph_types'][$g['type']][$g['subtype']] = $g;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Proces the config after it has been loaded.
|
|
* Make sure certain variables have been set properly and
|
|
*
|
|
*
|
|
*/
|
|
private static function processConfig()
|
|
{
|
|
if (!self::get('email_from')) {
|
|
self::set('email_from', '"' . self::get('project_name') . '" <' . self::get('email_user') . '@' . php_uname('n') . '>');
|
|
}
|
|
|
|
if (self::get('secure_cookies')) {
|
|
ini_set('session.cookie_secure', 1);
|
|
}
|
|
|
|
// deprecated variables
|
|
if (self::has('rrdgraph_real_95th')) {
|
|
self::set('rrdgraph_real_percentile', self::get('rrdgraph_real_95th'));
|
|
}
|
|
|
|
if (self::has('fping_options.millisec')) {
|
|
self::set('fping_options.interval', self::get('fping_options.millisec'));
|
|
}
|
|
|
|
if (self::has('discovery_modules.cisco-vrf')) {
|
|
self::set('discovery_modules.vrf', self::get('discovery_modules.cisco-vrf'));
|
|
}
|
|
|
|
// make sure we have full path to binaries in case PATH isn't set
|
|
foreach (array('fping', 'fping6', 'snmpgetnext', 'rrdtool') as $bin) {
|
|
if (!is_executable(self::get($bin))) {
|
|
self::set($bin, locate_binary($bin), true, $bin, "Path to $bin", 'external', 'paths');
|
|
}
|
|
}
|
|
}
|
|
}
|