mirror of
https://github.com/Cacti/plugin_thold.git
synced 2026-10-23 03:27:05 +09:00
8758 lines
282 KiB
PHP
8758 lines
282 KiB
PHP
<?php
|
|
/*
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2026 The Cacti Group |
|
|
| |
|
|
| 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 2 |
|
|
| 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. |
|
|
+-------------------------------------------------------------------------+
|
|
| Cacti: The Complete RRDTool-based Graphing Solution |
|
|
+-------------------------------------------------------------------------+
|
|
| This code is designed, written, and maintained by the Cacti Group. See |
|
|
| about.php and/or the AUTHORS file for specific developer information. |
|
|
+-------------------------------------------------------------------------+
|
|
| http://www.cacti.net/ |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
if (!defined('MESSAGE_LEVEL_NONE')) {
|
|
define('MESSAGE_LEVEL_NONE', 0);
|
|
define('MESSAGE_LEVEL_INFO', 1);
|
|
define('MESSAGE_LEVEL_WARN', 2);
|
|
define('MESSAGE_LEVEL_ERROR', 3);
|
|
define('MESSAGE_LEVEL_CSRF', 4);
|
|
}
|
|
|
|
if (!defined('STAT_HI')) {
|
|
define('STAT_HI', 2);
|
|
define('STAT_LO', 1);
|
|
define('STAT_NORMAL', 0);
|
|
}
|
|
|
|
if (!defined('THOLD_SEVERITY_NORMAL')) {
|
|
define('THOLD_SEVERITY_NORMAL', 0);
|
|
define('THOLD_SEVERITY_ALERT', 1);
|
|
define('THOLD_SEVERITY_WARNING', 2);
|
|
define('THOLD_SEVERITY_NOTICE', 3);
|
|
define('THOLD_SEVERITY_ACKREQ', 4);
|
|
define('THOLD_SEVERITY_DISABLED', 5);
|
|
define('THOLD_SEVERITY_BASELINE', 6);
|
|
}
|
|
|
|
/**
|
|
* sanitize_thold_sort_string - cleans up a search string submitted by the user to be passed
|
|
* to the database. NOTE: some of the code for this function came from the phpBB project.
|
|
*
|
|
* @param $string - the original raw search string
|
|
*
|
|
* @return - the sanitized search string
|
|
*/
|
|
function sanitize_thold_sort_string($string) {
|
|
static $drop_char_match = ['^', '$', '<', '>', '`', '\'', '"', '|', '?', '+', '[', ']', '{', '}', '#', ';', '!', '=', '*'];
|
|
static $drop_char_replace = [' ', ' ', ' ', ' ', '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '];
|
|
|
|
// Replace line endings by a space
|
|
$string = preg_replace('/[\n\r]/is', ' ', $string);
|
|
|
|
// HTML entities like
|
|
$string = preg_replace('/\b&[a-z]+;\b/', ' ', $string);
|
|
|
|
// Remove URL's
|
|
$string = preg_replace('/\b[a-z0-9]+:\/\/[a-z0-9\.\-]+(\/[a-z0-9\?\.%_\-\+=&\/]+)?/', ' ', $string);
|
|
|
|
// Filter out strange characters like ^, $, &, change "it's" to "its"
|
|
for ($i = 0; $i < cacti_count($drop_char_match); $i++) {
|
|
$string = str_replace($drop_char_match[$i], $drop_char_replace[$i], $string);
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
function get_time_since_last_event($thold) {
|
|
$local_data_id = $thold['local_data_id'];
|
|
|
|
if (empty($thold['instate']) || $thold['instate'] < 60) {
|
|
return __esc('< 1 Minute', 'thold');
|
|
}
|
|
|
|
if (time() - $thold['instate'] < 1000) {
|
|
return __esc('Since Created', 'thold');
|
|
}
|
|
|
|
switch($thold['thold_alert']) {
|
|
case '0':
|
|
return get_daysfromtime($thold['instate']);
|
|
|
|
break;
|
|
case '1':
|
|
case '2':
|
|
return get_daysfromtime($thold['instate']);
|
|
|
|
break;
|
|
default:
|
|
return __('Never', 'thold');
|
|
}
|
|
}
|
|
|
|
function thold_update_contacts() {
|
|
$users = db_fetch_assoc("SELECT id, 'email' AS type, email_address
|
|
FROM user_auth
|
|
WHERE email_address != ''");
|
|
|
|
if (cacti_sizeof($users)) {
|
|
foreach ($users as $u) {
|
|
$cid = db_fetch_cell_prepared('SELECT id
|
|
FROM plugin_thold_contacts
|
|
WHERE type="email"
|
|
AND user_id = ?',
|
|
[$u['id']]);
|
|
|
|
if ($cid) {
|
|
db_execute_prepared('REPLACE INTO plugin_thold_contacts
|
|
(id, user_id, type, data)
|
|
VALUES (?, ?, "email", ?)',
|
|
[$cid, $u['id'], $u['email_address']]);
|
|
} else {
|
|
db_execute_prepared('REPLACE INTO plugin_thold_contacts
|
|
(user_id, type, data)
|
|
VALUES (?, "email", ?)',
|
|
[$u['id'], $u['email_address']]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// cleanup old accounts
|
|
db_execute('DELETE ptc
|
|
FROM plugin_thold_contacts AS ptc
|
|
LEFT JOIN user_auth AS ua
|
|
ON ptc.user_id = ua.id
|
|
WHERE ua.email_address = ""
|
|
OR ua.id IS NULL');
|
|
}
|
|
|
|
function thold_tabs() {
|
|
global $config;
|
|
|
|
// present a tabbed interface
|
|
$tabs = [
|
|
'thold' => __('Thresholds', 'thold'),
|
|
'log' => __('Log', 'thold'),
|
|
'hoststat' => __('Device Status', 'thold')
|
|
];
|
|
|
|
$tabs = api_plugin_hook_function('thold_graph_tabs', $tabs);
|
|
|
|
get_filter_request_var('tab', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^([a-zA-Z]+)$/']]);
|
|
|
|
load_current_session_value('tab', 'sess_thold_graph_tab', 'general');
|
|
$current_tab = get_request_var('action');
|
|
|
|
// draw the tabs
|
|
print "<div class='tabs'><nav><ul>\n";
|
|
|
|
if (cacti_sizeof($tabs)) {
|
|
foreach (array_keys($tabs) as $tab_short_name) {
|
|
print "<li><a class='tab" . (($tab_short_name == $current_tab) ? " selected'" : "'") .
|
|
" href='" . html_escape($config['url_path'] .
|
|
'plugins/thold/thold_graph.php?' .
|
|
'action=' . $tab_short_name) .
|
|
"'>" . $tabs[$tab_short_name] . "</a></li>\n";
|
|
}
|
|
}
|
|
|
|
print "</ul></nav></div>\n";
|
|
}
|
|
|
|
function thold_debug($txt, $thread = '') {
|
|
global $debug;
|
|
|
|
if (read_config_option('thold_log_debug') == 'on' || $debug) {
|
|
thold_cacti_log($txt, $thread, true);
|
|
}
|
|
}
|
|
|
|
function thold_template_avail_devices($thold_template_id = 0) {
|
|
// display the host dropdown
|
|
if ($thold_template_id > 0) {
|
|
$graph_templates = array_rekey(db_fetch_assoc_prepared('SELECT DISTINCT gt.id
|
|
FROM graph_templates AS gt
|
|
INNER JOIN graph_templates_item AS gti
|
|
ON gt.id=gti.graph_template_id
|
|
AND local_graph_id=0
|
|
INNER JOIN data_template_rrd AS dtr
|
|
ON dtr.id=task_item_id
|
|
INNER JOIN thold_template AS tt
|
|
ON tt.data_template_id=dtr.data_template_id
|
|
INNER JOIN thold_data AS td
|
|
ON td.data_template_id=dtr.data_template_id
|
|
AND gt.id=td.graph_template_id
|
|
AND tt.id = ?',
|
|
[$thold_template_id]), 'id', 'id');
|
|
} else {
|
|
$graph_templates = array_rekey(db_fetch_assoc('SELECT DISTINCT gt.id
|
|
FROM graph_templates AS gt
|
|
INNER JOIN graph_templates_item AS gti
|
|
ON gt.id=gti.graph_template_id
|
|
AND local_graph_id=0
|
|
INNER JOIN data_template_rrd AS dtr
|
|
ON dtr.id=task_item_id
|
|
INNER JOIN thold_template AS tt
|
|
ON tt.data_template_id=dtr.data_template_id
|
|
INNER JOIN thold_data AS td
|
|
ON td.data_template_id=dtr.data_template_id
|
|
AND gt.id=td.graph_template_id'), 'id', 'id');
|
|
}
|
|
|
|
// Limit the hosts to only hosts that either have a graph template
|
|
// Listed as multiple, or do not have a threshold created
|
|
// Using the Graph Template listed
|
|
$device_ids = [];
|
|
|
|
if (cacti_sizeof($graph_templates)) {
|
|
$device_ids = array_rekey(db_fetch_assoc('SELECT DISTINCT rs.id
|
|
FROM (
|
|
SELECT h.id, gt.id AS gti, gt.multiple
|
|
FROM host AS h,graph_templates AS gt
|
|
) AS rs
|
|
LEFT JOIN graph_local AS gl
|
|
ON gl.graph_template_id=rs.gti
|
|
AND gl.host_id=rs.id
|
|
WHERE (gti IN(' . implode(', ', $graph_templates) . ')
|
|
AND host_id IS NULL)
|
|
OR rs.multiple = "on"'), 'id', 'id');
|
|
}
|
|
|
|
return (cacti_sizeof($device_ids) ? 'h.id IN (' . implode(', ', $device_ids) . ')' : '');
|
|
}
|
|
|
|
function thold_initialize_rusage() {
|
|
global $thold_start_rusage;
|
|
|
|
if (function_exists('getrusage')) {
|
|
$thold_start_rusage = getrusage();
|
|
}
|
|
|
|
$thold_start_rusage['microtime'] = microtime(true);
|
|
}
|
|
|
|
function thold_display_rusage() {
|
|
global $thold_start_rusage;
|
|
|
|
if (function_exists('getrusage')) {
|
|
$dat = getrusage();
|
|
|
|
html_start_box('', '100%', false, '3', 'left', '');
|
|
print '<tr>';
|
|
|
|
if (!isset($thold_start_rusage)) {
|
|
print "<td colspan='10'>ERROR: Can not display RUSAGE please call thold_initialize_rusage first</td>";
|
|
} else {
|
|
$i_u_time = $thold_start_rusage['ru_utime.tv_sec'] + ($thold_start_rusage['ru_utime.tv_usec'] * 1E-6);
|
|
$i_s_time = $thold_start_rusage['ru_stime.tv_sec'] + ($thold_start_rusage['ru_stime.tv_usec'] * 1E-6);
|
|
$s_s = $thold_start_rusage['ru_nswap'];
|
|
$s_pf = $thold_start_rusage['ru_majflt'];
|
|
|
|
$start_time = $thold_start_rusage['microtime'];
|
|
$end_time = microtime(true);
|
|
|
|
$utime = ($dat['ru_utime.tv_sec'] + ($dat['ru_utime.tv_usec'] * 1E-6)) - $i_u_time;
|
|
$stime = ($dat['ru_stime.tv_sec'] + ($dat['ru_stime.tv_usec'] * 1E-6)) - $i_s_time;
|
|
$swaps = $dat['ru_nswap'] - $s_s;
|
|
$pages = $dat['ru_majflt'] - $s_pf;
|
|
|
|
print "<td colspan='10' width='1%' style='text-align:left;'>";
|
|
print '<b>' . __('Time:', 'thold') . '</b> ' . round($end_time - $start_time,2) . ' seconds, ';
|
|
print '<b>' . __('User:', 'thold') . '</b> ' . round($utime,2) . ' seconds, ';
|
|
print '<b>' . __('System:', 'thold') . '</b> ' . round($stime,2) . ' seconds, ';
|
|
print '<b>' . __('Swaps:', 'thold') . '</b> ' . ($swaps) . ' swaps, ';
|
|
print '<b>' . __('Pages:', 'thold') . '</b> ' . ($pages) . ' pages';
|
|
print '</td>';
|
|
}
|
|
|
|
print '</tr>';
|
|
html_end_box(false);
|
|
}
|
|
}
|
|
|
|
function thold_legend() {
|
|
global $thold_states;
|
|
|
|
html_start_box('', '100%', false, '3', 'center', '');
|
|
|
|
print '<tr class="tableRow">';
|
|
|
|
foreach ($thold_states as $index => $state) {
|
|
print "<td class='" . $state['class'] . "'>" . $state['display'] . '</td>';
|
|
}
|
|
print '</tr>';
|
|
|
|
html_end_box(false);
|
|
}
|
|
|
|
function host_legend() {
|
|
global $thold_host_states;
|
|
|
|
html_start_box('', '100%', false, '3', 'center', '');
|
|
|
|
print '<tr class="tableRow">';
|
|
|
|
foreach ($thold_host_states as $index => $state) {
|
|
print "<td class='" . $state['class'] . "'>" . $state['display'] . '</td>';
|
|
}
|
|
print '</tr>';
|
|
|
|
html_end_box(false);
|
|
}
|
|
|
|
function log_legend() {
|
|
global $thold_log_states;
|
|
|
|
html_start_box('', '100%', false, '3', 'center', '');
|
|
|
|
print '<tr class="tableRow">';
|
|
|
|
foreach ($thold_log_states as $index => $state) {
|
|
print "<td class='" . $state['class'] . "'>" . $state['display_short'] . '</td>';
|
|
}
|
|
print '</tr>';
|
|
|
|
html_end_box(false);
|
|
}
|
|
|
|
function thold_expression_rpn_pop(&$stack) {
|
|
global $rpn_error;
|
|
|
|
if (cacti_sizeof($stack)) {
|
|
return array_pop($stack);
|
|
} else {
|
|
$rpn_error = true;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function thold_expression_math_rpn($operator, &$stack) {
|
|
global $rpn_error;
|
|
|
|
$orig_stack = $stack;
|
|
|
|
switch($operator) {
|
|
case '+':
|
|
case '-':
|
|
case '/':
|
|
case '*':
|
|
case '%':
|
|
case '^':
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
$v3 = 'U';
|
|
|
|
$rpn_evaled = false;
|
|
|
|
if (!is_numeric($v1)) {
|
|
cacti_log('ERROR: RPN value: v1 "' . $v1 . '" is Not valid for operator "' . $operator . '". Stack:"' . implode(',', $orig_stack) . '"', false, 'THOLD');
|
|
$rpn_error = true;
|
|
} elseif (!is_numeric($v2)) {
|
|
cacti_log('ERROR: RPN value: v2 "' . $v2 . '" is Not valid for operator "' . $operator . '". Stack:"' . implode(',', $orig_stack) . '"', false, 'THOLD');
|
|
$rpn_error = true;
|
|
} elseif ($v1 == 0 && $v2 == 0 && $operator == '/') {
|
|
$v3 = 0;
|
|
$rpn_evaled = true;
|
|
|
|
break;
|
|
} elseif ($v1 == 0 && $operator == '/') {
|
|
cacti_log('ERROR: RPN value: v1 can not be "0" when the operator is "/". Stack:"' . implode(',', $orig_stack) . '"', false, 'THOLD');
|
|
$rpn_error = true;
|
|
}
|
|
|
|
if ($rpn_evaled) {
|
|
array_push($stack, $v3);
|
|
} elseif (!$rpn_error) {
|
|
eval('$v3 = ' . $v2 . ' ' . $operator . ' ' . $v1 . ';');
|
|
|
|
if ($v3 == '') {
|
|
$v3 = 0;
|
|
}
|
|
|
|
array_push($stack, $v3);
|
|
}
|
|
|
|
break;
|
|
case 'SIN':
|
|
case 'COS':
|
|
case 'TAN':
|
|
case 'ATAN':
|
|
case 'SQRT':
|
|
case 'FLOOR':
|
|
case 'CEIL':
|
|
case 'DEG2RAD':
|
|
case 'RAD2DEG':
|
|
case 'ABS':
|
|
case 'EXP':
|
|
case 'LOG':
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
|
|
if (!$rpn_error) {
|
|
eval('$v2 = ' . $operator . '(' . $v1 . ');');
|
|
array_push($stack, $v2);
|
|
}
|
|
|
|
break;
|
|
case 'ATAN2':
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
|
|
if (!$rpn_error) {
|
|
$v3 = atan2($v1, $v2);
|
|
array_push($stack, $v3);
|
|
}
|
|
|
|
break;
|
|
case 'ADDNAN':
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
|
|
if (!$rpn_error) {
|
|
if ($v1 == 'NAN' || $v1 == 'U') {
|
|
$v1 = 0;
|
|
}
|
|
|
|
if ($v2 == 'NAN' || $v2 == 'U') {
|
|
$v2 = 0;
|
|
}
|
|
array_push($stack, $v1 + $v2);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
function thold_expression_boolean_rpn($operator, &$stack) {
|
|
global $rpn_error;
|
|
|
|
if ($operator == 'UN') {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
|
|
if ($v1 == 'U' || $v1 == 'NAN') {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
} elseif ($operator == 'ISINF') {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
|
|
if ($v1 == 'INF' || $v1 == 'NEGINF') {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
} elseif ($operator == 'AND') {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
|
|
if ($v1 > 0 && $v2 > 0) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
} elseif ($operator == 'OR') {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
|
|
if ($v1 > 0 || $v2 > 0) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
} elseif ($operator == 'IF') {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
$v3 = thold_expression_rpn_pop($stack);
|
|
|
|
if ($v3 == 0) {
|
|
array_push($stack, $v1);
|
|
} else {
|
|
array_push($stack, $v2);
|
|
}
|
|
} else {
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
|
|
// deal with unknown or infinite data
|
|
if (($v1 == 'INF' || $v2 == 'INF') ||
|
|
($v1 == 'NAN' || $v2 == 'NAN') ||
|
|
($v1 == 'U' || $v2 == 'U') ||
|
|
($v1 == 'NEGINF' || $v2 == 'NEGINF')) {
|
|
array_push($stack, '0');
|
|
}
|
|
|
|
switch($operator) {
|
|
case 'LT':
|
|
if ($v1 < $v2) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
|
|
break;
|
|
case 'GT':
|
|
if ($v1 > $v2) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
|
|
break;
|
|
case 'LE':
|
|
if ($v1 <= $v2) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
|
|
break;
|
|
case 'GE':
|
|
if ($v1 >= $v2) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
|
|
break;
|
|
case 'EQ':
|
|
if ($v1 == $v2) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
|
|
break;
|
|
case 'NE':
|
|
if ($v1 != $v2) {
|
|
array_push($stack, '1');
|
|
} else {
|
|
array_push($stack, '0');
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_expression_compare_rpn($operator, &$stack) {
|
|
global $rpn_error;
|
|
|
|
if ($operator == 'MAX' || $operator == 'MIN') {
|
|
$v[0] = thold_expression_rpn_pop($stack);
|
|
$v[1] = thold_expression_rpn_pop($stack);
|
|
|
|
if (in_array('INF', $v, true)) {
|
|
array_push($stack, 'INF');
|
|
} elseif (in_array('NEGINF', $v, true)) {
|
|
array_push($stack, 'NEGINF');
|
|
} elseif (in_array('U', $v, true)) {
|
|
array_push($stack, 'U');
|
|
} elseif (in_array('NAN', $v, true)) {
|
|
array_push($stack, 'NAN');
|
|
} elseif ($operator == 'MAX') {
|
|
array_push($stack, max($v));
|
|
} else {
|
|
array_push($stack, min($v));
|
|
}
|
|
} else {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
$v3 = thold_expression_rpn_pop($stack);
|
|
|
|
if (($v1 == 'U' || $v1 == 'NAN') ||
|
|
($v2 == 'U' || $v2 == 'NAN') ||
|
|
($v3 == 'U' || $v3 == 'NAN')) {
|
|
array_push($stack, 'U');
|
|
} elseif (($v1 == 'INF' || $v1 == 'NEGINF') ||
|
|
($v2 == 'INF' || $v2 == 'NEGINF') ||
|
|
($v3 == 'INF' || $v3 == 'NEGINF')) {
|
|
array_push($stack, 'U');
|
|
} elseif ($v1 < $v2) {
|
|
if ($v3 >= $v1 && $v3 <= $v2) {
|
|
array_push($stack, $v3);
|
|
} else {
|
|
array_push($stack, 'U');
|
|
}
|
|
} else {
|
|
if ($v3 >= $v2 && $v3 <= $v1) {
|
|
array_push($stack, $v3);
|
|
} else {
|
|
array_push($stack, 'U');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_expression_specvals_rpn($operator, &$stack, $count) {
|
|
global $rpn_error;
|
|
|
|
if ($operator == 'UNKN') {
|
|
array_push($stack, 'U');
|
|
} elseif ($operator == 'INF') {
|
|
array_push($stack, 'INF');
|
|
} elseif ($operator == 'NEGINF') {
|
|
array_push($stack, 'NEGINF');
|
|
} elseif ($operator == 'COUNT') {
|
|
array_push($stack, $count);
|
|
} elseif ($operator == 'PREV') {
|
|
// still have to figure this out
|
|
}
|
|
}
|
|
|
|
function thold_expression_stackops_rpn($operator, &$stack) {
|
|
global $rpn_error;
|
|
|
|
if ($operator == 'DUP') {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
array_push($stack, $v1);
|
|
array_push($stack, $v1);
|
|
} elseif ($operator == 'POP') {
|
|
thold_expression_rpn_pop($stack);
|
|
} else {
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
array_push($stack, $v2);
|
|
array_push($stack, $v1);
|
|
}
|
|
}
|
|
|
|
function thold_expression_time_rpn($operator, &$stack) {
|
|
global $rpn_error;
|
|
|
|
if ($operator == 'NOW') {
|
|
array_push($stack, time());
|
|
} elseif ($operator == 'TIME') {
|
|
// still need to figure this one out
|
|
} elseif ($operator == 'LTIME') {
|
|
// still need to figure this one out
|
|
}
|
|
}
|
|
|
|
function thold_expression_setops_rpn($operator, &$stack) {
|
|
global $rpn_error;
|
|
|
|
if ($operator == 'SORT') {
|
|
$count = thold_expression_rpn_pop($stack);
|
|
$v = [];
|
|
|
|
if ($count > 0) {
|
|
for ($i = 0; $i < $count; $i++) {
|
|
$v[] = thold_expression_rpn_pop($stack);
|
|
}
|
|
|
|
sort($v, SORT_NUMERIC);
|
|
|
|
foreach ($v as $val) {
|
|
array_push($stack, $val);
|
|
}
|
|
}
|
|
} elseif ($operator == 'REV') {
|
|
$count = thold_expression_rpn_pop($stack);
|
|
$v = [];
|
|
|
|
if ($count > 0) {
|
|
for ($i = 0; $i < $count; $i++) {
|
|
$v[] = thold_expression_rpn_pop($stack);
|
|
}
|
|
|
|
$v = array_reverse($v);
|
|
|
|
foreach ($v as $val) {
|
|
array_push($stack, $val);
|
|
}
|
|
}
|
|
} elseif ($operator == 'AVG') {
|
|
$count = thold_expression_rpn_pop($stack);
|
|
|
|
if ($count > 0) {
|
|
$total = 0;
|
|
$inf = false;
|
|
$neginf = false;
|
|
|
|
for ($i = 0; $i < $count; $i++) {
|
|
$v = thold_expression_rpn_pop($stack);
|
|
|
|
if ($v == 'INF') {
|
|
$inf = true;
|
|
} elseif ($v == 'NEGINF') {
|
|
$neginf = true;
|
|
} else {
|
|
$total += $v;
|
|
}
|
|
}
|
|
|
|
if ($inf) {
|
|
array_push($stack, 'INF');
|
|
} elseif ($neginf) {
|
|
array_push($stack, 'NEGINF');
|
|
} else {
|
|
array_push($stack, $total / $count);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_expression_ds_value($operator, &$stack, $data_sources) {
|
|
global $rpn_error;
|
|
|
|
if (cacti_sizeof($data_sources)) {
|
|
foreach ($data_sources as $rrd_name => $value) {
|
|
if (strtoupper($rrd_name) == $operator) {
|
|
array_push($stack, $value);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
array_push($stack, 0);
|
|
}
|
|
|
|
function thold_expression_specialtype_rpn($operator, &$stack, $local_data_id, $currentval) {
|
|
switch ($operator) {
|
|
case 'CURRENT_DATA_SOURCE':
|
|
array_push($stack, $currentval);
|
|
|
|
break;
|
|
case 'CURRENT_GRAPH_MAXIMUM_VALUE':
|
|
array_push($stack, get_current_value($local_data_id, 'upper_limit'));
|
|
|
|
break;
|
|
case 'CURRENT_GRAPH_MINIMUM_VALUE':
|
|
array_push($stack, get_current_value($local_data_id, 'lower_limit'));
|
|
|
|
break;
|
|
case 'CURRENT_DS_MINIMUM_VALUE':
|
|
array_push($stack, get_current_value($local_data_id, 'rrd_minimum'));
|
|
|
|
break;
|
|
case 'CURRENT_DS_MAXIMUM_VALUE':
|
|
array_push($stack, get_current_value($local_data_id, 'rrd_maximum'));
|
|
|
|
break;
|
|
case 'VALUE_OF_HDD_TOTAL':
|
|
array_push($stack, get_current_value($local_data_id, 'hdd_total'));
|
|
|
|
break;
|
|
case 'ALL_DATA_SOURCES_NODUPS':
|
|
case 'ALL_DATA_SOURCES_DUPS':
|
|
$v1 = 0;
|
|
|
|
$all_dsns = db_fetch_assoc_prepared('SELECT data_source_name
|
|
FROM data_template_rrd
|
|
WHERE local_data_id = ?',
|
|
[$local_data_id]);
|
|
|
|
if (cacti_sizeof($all_dsns)) {
|
|
foreach ($all_dsns as $dsn) {
|
|
$v1 += get_current_value($local_data_id, $dsn['data_source_name']);
|
|
}
|
|
}
|
|
|
|
array_push($stack, $v1);
|
|
|
|
break;
|
|
default:
|
|
cacti_log('WARNING: CDEF property not implemented yet: ' . $operator, false, 'THOLD', POLLER_VERBOSITY_MEDIUM);
|
|
array_push($stack, $currentval);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
function thold_get_currentval(&$thold_data, &$rrd_reindexed, &$rrd_time_reindexed, &$item, &$currenttime) {
|
|
// adjust the polling interval by the last read, if applicable
|
|
$currenttime = $rrd_time_reindexed[$thold_data['local_data_id']];
|
|
|
|
if ($thold_data['lasttime'] > 0) {
|
|
if (is_numeric($currenttime)) {
|
|
$step = $currenttime - $thold_data['lasttime'];
|
|
} else {
|
|
$step = $thold_data['rrd_step'];
|
|
}
|
|
} else {
|
|
$step = $thold_data['rrd_step'];
|
|
}
|
|
|
|
if (empty($step)) {
|
|
$step = read_config_option('poller_interval');
|
|
}
|
|
|
|
$currentval = '';
|
|
|
|
if (isset($rrd_reindexed[$thold_data['local_data_id']])) {
|
|
$item = $rrd_reindexed[$thold_data['local_data_id']];
|
|
|
|
if (isset($item[$thold_data['name']]) && is_numeric($item[$thold_data['name']])) {
|
|
switch ($thold_data['data_source_type_id']) {
|
|
case 2: // COUNTER
|
|
if ($thold_data['oldvalue'] != 0 && is_numeric($thold_data['oldvalue'])) {
|
|
if ($item[$thold_data['name']] >= $thold_data['oldvalue']) {
|
|
// Everything is Normal
|
|
$currentval = $item[$thold_data['name']] - $thold_data['oldvalue'];
|
|
} else {
|
|
// Possible overflow, see if its 32bit or 64bit
|
|
if ($thold_data['oldvalue'] > 4294967295) {
|
|
$currentval = (18446744073709551615 - $thold_data['oldvalue']) + $item[$thold_data['name']];
|
|
} else {
|
|
$currentval = (4294967295 - $thold_data['oldvalue']) + $item[$thold_data['name']];
|
|
}
|
|
}
|
|
|
|
if (strpos($thold_data['rrd_maximum'], '|query_') !== false) {
|
|
$data_local = db_fetch_row_prepared('SELECT *
|
|
FROM data_local
|
|
WHERE id = ?',
|
|
[$thold_data['local_data_id']]);
|
|
|
|
if ($thold_data['rrd_maximum'] == '|query_ifSpeed|' || $thold_data['rrd_maximum'] == '|query_ifHighSpeed|') {
|
|
$highSpeed = db_fetch_cell_prepared("SELECT field_value
|
|
FROM host_snmp_cache
|
|
WHERE host_id = ?
|
|
AND snmp_query_id = ?
|
|
AND snmp_index = ?
|
|
AND field_name = 'ifHighSpeed'",
|
|
[$data_local['host_id'], $data_local['snmp_query_id'], $data_local['snmp_index']]);
|
|
|
|
if (!empty($highSpeed)) {
|
|
$thold_data['rrd_maximum'] = $highSpeed * 1000000;
|
|
} else {
|
|
$thold_data['rrd_maximum'] = substitute_snmp_query_data('|query_ifSpeed|', $data_local['host_id'], $data_local['snmp_query_id'], $data_local['snmp_index']);
|
|
}
|
|
} else {
|
|
$thold_data['rrd_maximum'] = substitute_snmp_query_data($thold_data['rrd_maximum'], $data_local['host_id'], $data_local['snmp_query_id'], $data_local['snmp_index']);
|
|
}
|
|
}
|
|
|
|
// assume counter reset if greater than max value
|
|
if ($thold_data['rrd_maximum'] > 0 && ($currentval / $step) > $thold_data['rrd_maximum']) {
|
|
$currentval = $item[$thold_data['name']] / $step;
|
|
} elseif ($thold_data['rrd_maximum'] == 0 && $currentval > 4.25E+9) {
|
|
$currentval = $item[$thold_data['name']] / $step;
|
|
} else {
|
|
$currentval = $currentval / $step;
|
|
}
|
|
} else {
|
|
$currentval = 0;
|
|
}
|
|
|
|
break;
|
|
case 3: // DERIVE
|
|
$currentval = ($item[$thold_data['name']] - $thold_data['oldvalue']) / $step;
|
|
|
|
break;
|
|
case 4: // ABSOLUTE
|
|
$currentval = $item[$thold_data['name']] / $step;
|
|
|
|
break;
|
|
case 1: // GAUGE
|
|
default:
|
|
$currentval = $item[$thold_data['name']];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $currentval;
|
|
}
|
|
|
|
function thold_calculate_expression($thold, $currentval, &$rrd_reindexed, &$rrd_time_reindexed) {
|
|
global $rpn_error;
|
|
|
|
// set an rpn error flag
|
|
$rpn_error = false;
|
|
|
|
// operators to support
|
|
$math = ['+', '-', '*', '/', '%', '^', 'ADDNAN', 'SIN', 'COS', 'LOG', 'EXP',
|
|
'SQRT', 'ATAN', 'ATAN2', 'FLOOR', 'CEIL', 'DEG2RAD', 'RAD2DEG', 'ABS'];
|
|
$boolean = ['LT', 'LE', 'GT', 'GE', 'EQ', 'NE', 'UN', 'ISNF', 'IF', 'AND', 'OR'];
|
|
$comparison = ['MIN', 'MAX', 'LIMIT'];
|
|
$setops = ['SORT', 'REV', 'AVG'];
|
|
$specvals = ['UNKN', 'INF', 'NEGINF', 'PREV', 'COUNT'];
|
|
$stackops = ['DUP', 'POP', 'EXC'];
|
|
$time = ['NOW', 'TIME', 'LTIME'];
|
|
$spectypes = ['CURRENT_DATA_SOURCE', 'CURRENT_GRAPH_MINIMUM_VALUE',
|
|
'CURRENT_GRAPH_MINIMUM_VALUE', 'CURRENT_DS_MINIMUM_VALUE',
|
|
'CURRENT_DS_MAXIMUM_VALUE', 'VALUE_OF_HDD_TOTAL',
|
|
'ALL_DATA_SOURCES_NODUPS', 'ALL_DATA_SOURCES_DUPS'];
|
|
|
|
// our expression array
|
|
$expression = explode(',', $thold['expression']);
|
|
|
|
// out current data sources
|
|
$data_sources = $rrd_reindexed[$thold['local_data_id']];
|
|
|
|
if (cacti_sizeof($data_sources)) {
|
|
foreach ($data_sources as $key => $value) {
|
|
$nds[$key] = $value;
|
|
}
|
|
|
|
$data_sources = $nds;
|
|
}
|
|
|
|
// replace all data tabs in the rpn with values
|
|
if (cacti_sizeof($expression)) {
|
|
foreach ($expression as $key => $item) {
|
|
if (strpos($item, '|ds:') !== false) {
|
|
// Remove invalid characters
|
|
$item = str_replace('\\', '', $item);
|
|
|
|
$dsname = trim(str_replace('|ds:', '', $item), " |\n\r");
|
|
|
|
$thold_item = db_fetch_row_prepared('SELECT td.id, td.local_graph_id,
|
|
td.percent_ds, td.expression, td.upper_ds, td.data_type,
|
|
td.host_id, td.cdef, td.local_data_id,
|
|
td.data_template_rrd_id, td.lastread, UNIX_TIMESTAMP(td.lasttime) AS lasttime,
|
|
td.oldvalue, dtr.data_source_name as name,
|
|
dtr.data_source_type_id, dtd.rrd_step, dtr.rrd_maximum
|
|
FROM thold_data AS td
|
|
LEFT JOIN data_template_rrd AS dtr
|
|
ON dtr.id = td.data_template_rrd_id
|
|
LEFT JOIN data_template_data AS dtd
|
|
ON dtd.local_data_id=td.local_data_id
|
|
WHERE dtr.data_source_name = ?
|
|
AND td.local_data_id = ?',
|
|
[$dsname, $thold['local_data_id']]);
|
|
|
|
$value = '';
|
|
|
|
if (cacti_sizeof($thold_item)) {
|
|
$item = [];
|
|
$currenttime = 0;
|
|
$value = thold_get_currentval($thold_item, $rrd_reindexed, $rrd_time_reindexed, $item, $currenttime);
|
|
}
|
|
|
|
// Previous returns 'U' after device recovers. Try alternate
|
|
if (empty($value) || $value == 'U') {
|
|
if (read_config_option('dsstats_enable') == 'on') {
|
|
$value = db_fetch_cell_prepared('SELECT calculated
|
|
FROM data_source_stats_hourly_last
|
|
WHERE local_data_id = ?
|
|
AND rrd_name = ?',
|
|
[$thold['local_data_id'], $dsname]);
|
|
}
|
|
|
|
if (empty($value) || $value = 'U' || $value == '-90909090909') {
|
|
$value = get_current_value($thold['local_data_id'], $dsname);
|
|
}
|
|
}
|
|
|
|
$expression[$key] = $value;
|
|
|
|
if ($expression[$key] == '') {
|
|
$expression[$key] = '0';
|
|
}
|
|
} elseif (strpos($item, '|') !== false) {
|
|
// Remove invalid characters
|
|
$item = str_replace('\\', '', $item);
|
|
|
|
$gl = db_fetch_row_prepared('SELECT *
|
|
FROM graph_local
|
|
WHERE id = ?',
|
|
[$thold['local_graph_id']]);
|
|
|
|
if (cacti_sizeof($gl)) {
|
|
$expression[$key] = thold_expand_string($thold, $item);
|
|
} else {
|
|
$expression[$key] = '0';
|
|
cacti_log("WARNING: Query Replacement for '$item' Does Not Exist");
|
|
}
|
|
|
|
if ($expression[$key] == '') {
|
|
$expression[$key] = '0';
|
|
}
|
|
} else {
|
|
// normal operator
|
|
}
|
|
}
|
|
}
|
|
|
|
$processed_expression = $expression;
|
|
|
|
// cacti_log(implode(',', array_keys($data_sources)));
|
|
// cacti_log(implode(',', $data_sources));
|
|
// cacti_log(implode(',', $expression));
|
|
|
|
// now let's process the RPN stack
|
|
$x = count($expression);
|
|
|
|
if ($x == 0) {
|
|
return $currentval;
|
|
}
|
|
|
|
// operation stack for RPN
|
|
$stack = [];
|
|
|
|
// current pointer in the RPN operations list
|
|
$cursor = 0;
|
|
|
|
while ($cursor < $x) {
|
|
$operator = strtoupper(trim($expression[$cursor]));
|
|
|
|
if (stripos($operator, '|query_ifHighSpeed') !== false || stripos($operator, '|query_ifSpeed') !== false) {
|
|
$data_local = db_fetch_row_prepared('SELECT *
|
|
FROM data_local
|
|
WHERE id = ?',
|
|
[$thold['local_data_id']]);
|
|
|
|
$operator = rrdtool_function_interface_speed($data_local);
|
|
}
|
|
|
|
// is the operator a data source
|
|
if (is_numeric($operator)) {
|
|
// cacti_log("NOTE: Numeric '$operator'", false, "THOLD");
|
|
array_push($stack, $operator);
|
|
} elseif (array_key_exists($operator, $data_sources)) {
|
|
// cacti_log("NOTE: DS Value '$operator'", false, "THOLD");
|
|
thold_expression_ds_value($operator, $stack, $data_sources);
|
|
} elseif (in_array($operator, $comparison, true)) {
|
|
// cacti_log("NOTE: Compare '$operator'", false, "THOLD");
|
|
thold_expression_compare_rpn($operator, $stack);
|
|
} elseif (in_array($operator, $boolean, true)) {
|
|
// cacti_log("NOTE: Boolean '$operator'", false, "THOLD");
|
|
thold_expression_boolean_rpn($operator, $stack);
|
|
} elseif (in_array($operator, $math, true)) {
|
|
// cacti_log("NOTE: Math '$operator'", false, "THOLD");
|
|
thold_expression_math_rpn($operator, $stack);
|
|
} elseif (in_array($operator, $setops, true)) {
|
|
// cacti_log("NOTE: SetOps '$operator'", false, "THOLD");
|
|
thold_expression_setops_rpn($operator, $stack);
|
|
} elseif (in_array($operator, $specvals, true)) {
|
|
// cacti_log("NOTE: SpecVals '$operator'", false, "THOLD");
|
|
thold_expression_specvals_rpn($operator, $stack, $cursor + 2);
|
|
} elseif (in_array($operator, $stackops, true)) {
|
|
// cacti_log("NOTE: StackOps '$operator'", false, "THOLD");
|
|
thold_expression_stackops_rpn($operator, $stack);
|
|
} elseif (in_array($operator, $time, true)) {
|
|
// cacti_log("NOTE: Time '$operator'", false, "THOLD");
|
|
thold_expression_time_rpn($operator, $stack);
|
|
} elseif (in_array($operator, $spectypes, true)) {
|
|
// cacti_log("NOTE: SpecialTypes '$operator'", false, "THOLD");
|
|
thold_expression_specialtype_rpn($operator, $stack, $thold['local_data_id'], $currentval);
|
|
} else {
|
|
cacti_log("WARNING: Unsupported Field '$operator'", false, 'THOLD');
|
|
$rpn_error = true;
|
|
}
|
|
|
|
$cursor++;
|
|
|
|
if ($rpn_error) {
|
|
cacti_log("ERROR: RPN Expression is invalid! THold:'" . $thold['name'] . "', Value:'" . $currentval . "', Expression:'" . $thold['expression'] . "', Processed:'" . implode(',', $processed_expression) . "'", false, 'THOLD');
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return $stack[0];
|
|
}
|
|
|
|
function thold_substitute_snmp_query_data($string, $device_id, $snmp_query_id, $snmp_index, $max_chars = 0) {
|
|
$field_name = trim(str_replace('|query_', '', $string),"| \n\r");
|
|
|
|
$snmp_cache_data = db_fetch_cell_prepared('SELECT field_value
|
|
FROM host_snmp_cache
|
|
WHERE host_id = ?
|
|
AND snmp_query_id = ?
|
|
AND snmp_index = ?
|
|
AND field_name= ?',
|
|
[$device_id, $snmp_query_id, $snmp_index, $field_name]);
|
|
|
|
if ($snmp_cache_data != '') {
|
|
return $snmp_cache_data;
|
|
} else {
|
|
return $string;
|
|
}
|
|
}
|
|
|
|
function thold_substitute_data_source_description($string, $local_data_id, $max_chars = 0) {
|
|
$field_name = trim(str_replace('|data_source_description', '', $string),"| \n\r");
|
|
|
|
$cache_data = db_fetch_cell_prepared('SELECT name_cache
|
|
FROM data_template_data
|
|
WHERE local_data_id = ?
|
|
LIMIT 1',
|
|
[$local_data_id]);
|
|
|
|
if ($cache_data != '') {
|
|
return $cache_data;
|
|
} else {
|
|
return $string;
|
|
}
|
|
}
|
|
|
|
function thold_substitute_host_data($string, $l_escape_string, $r_escape_string, $device_id) {
|
|
$field_name = trim(str_replace('|host_', '', $string),"| \n\r");
|
|
|
|
if (!isset($_SESSION['sess_host_cache_array'][$device_id])) {
|
|
$host = db_fetch_row_prepared('SELECT *
|
|
FROM host WHERE id = ?',
|
|
[$device_id]);
|
|
|
|
$_SESSION['sess_host_cache_array'][$device_id] = $host;
|
|
}
|
|
|
|
if (isset($_SESSION['sess_host_cache_array'][$device_id][$field_name])) {
|
|
return $_SESSION['sess_host_cache_array'][$device_id][$field_name];
|
|
}
|
|
|
|
$string = str_replace($l_escape_string . 'host_management_ip' . $r_escape_string, $_SESSION['sess_host_cache_array'][$device_id]['hostname'], $string);
|
|
$temp = api_plugin_hook_function('substitute_host_data', ['string' => $string, 'l_escape_string' => $l_escape_string, 'r_escape_string' => $r_escape_string, 'host_id' => $device_id]);
|
|
$string = $temp['string'];
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* thold_substitute_custom_data - takes a string and substitutes all custom data variables contained in it
|
|
*
|
|
* @param $string - the string to make custom data variable substitutions on
|
|
* @param $l_escape_string - the character used to escape each variable on the left side
|
|
* @param $r_escape_string - the character used to escape each variable on the right side
|
|
* @param $local_data_id - (int) the local_data_id to match
|
|
* @param mixed $l_escape
|
|
* @param mixed $r_escape
|
|
*
|
|
* @return - the original string with all of the variable substitutions made
|
|
*/
|
|
function thold_substitute_custom_data($string, $l_escape, $r_escape, $local_data_id) {
|
|
if (is_array($local_data_id)) {
|
|
$local_data_ids = $local_data_id;
|
|
} elseif ($local_data_id == '') {
|
|
return;
|
|
} else {
|
|
$local_data_ids = [$local_data_id];
|
|
}
|
|
|
|
$match = $l_escape . 'custom_';
|
|
$matches = [];
|
|
$inclause = [];
|
|
$query_array = [];
|
|
$cur_pos = 0;
|
|
|
|
while (true) {
|
|
$start_pos = strpos($string, $match, $cur_pos);
|
|
|
|
if ($start_pos !== false) {
|
|
$cur_pos = strpos($string, $r_escape, $start_pos + 1);
|
|
$cfield = substr($string, $start_pos, $cur_pos - $start_pos + 1);
|
|
$cfield = trim(str_replace($match, '', $cfield), " \n\r\t$r_escape");
|
|
$matches[] = $cfield;
|
|
$inclause[] = '?';
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cacti_sizeof($matches)) {
|
|
$ids = array_rekey(
|
|
db_fetch_assoc('SELECT id
|
|
FROM data_template_data
|
|
WHERE local_data_id IN (' . implode(', ', $local_data_ids) . ')'),
|
|
'id', 'id'
|
|
);
|
|
|
|
if (cacti_sizeof($ids)) {
|
|
$data_template_data_ids = implode(', ', $ids);
|
|
|
|
foreach ($matches as $match) {
|
|
$query_array[] = $match;
|
|
}
|
|
|
|
$custom_data_array = db_fetch_assoc_prepared('SELECT
|
|
dif.data_name AS name, did.value
|
|
FROM data_input_fields AS dif
|
|
INNER JOIN data_input_data AS did
|
|
ON did.data_input_field_id = dif.id
|
|
WHERE did.data_template_data_id IN (' . $data_template_data_ids . ')
|
|
AND data_name IN (' . implode(', ', $inclause) . ')',
|
|
$query_array);
|
|
|
|
if (cacti_sizeof($custom_data_array)) {
|
|
foreach ($custom_data_array as $custom_data) {
|
|
$custom_name = $custom_data['name'];
|
|
$custom_value = $custom_data['value'];
|
|
$string = str_replace($l_escape . 'custom_' . $custom_name . $r_escape, $custom_value, $string);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
function thold_calculate_percent($thold, $currentval, $rrd_reindexed) {
|
|
$ds = $thold['percent_ds'];
|
|
|
|
if (!is_numeric($currentval)) {
|
|
return '';
|
|
}
|
|
|
|
if (isset($rrd_reindexed[$thold['local_data_id']][$ds])) {
|
|
$t = (int) $rrd_reindexed[$thold['local_data_id']][$thold['percent_ds']];
|
|
|
|
if ($t > 0) {
|
|
$currentval = ($currentval / $t) * 100;
|
|
} else {
|
|
$currentval = 0;
|
|
}
|
|
} else {
|
|
$currentval = '';
|
|
}
|
|
|
|
return $currentval;
|
|
}
|
|
|
|
function thold_calculate_lower_upper($thold, $currentval, $rrd_reindexed) {
|
|
$ds = $thold['upper_ds'];
|
|
|
|
if (isset($rrd_reindexed[$thold['local_data_id']][$ds])) {
|
|
$t = $rrd_reindexed[$thold['local_data_id']][$thold['upper_ds']];
|
|
$currentval = ($t << 32) + $currentval;
|
|
}
|
|
|
|
return $currentval;
|
|
}
|
|
|
|
function get_allowed_thresholds($sql_where = '', $order_by = 'td.name', $sql_limit = '', &$total_rows = 0, $user_id = 0, $graph_id = 0) {
|
|
if ($sql_limit != '') {
|
|
$sql_limit = "LIMIT $sql_limit";
|
|
}
|
|
|
|
if ($order_by != '') {
|
|
$order_by = "ORDER BY $order_by";
|
|
}
|
|
|
|
if ($graph_id > 0) {
|
|
$sql_where .= (strlen($sql_where) ? ' AND ' : ' ') . " gl.id=$graph_id";
|
|
}
|
|
|
|
if (strlen($sql_where)) {
|
|
$sql_where = "WHERE $sql_where";
|
|
}
|
|
|
|
if ($user_id == -1) {
|
|
$auth_method = 0;
|
|
} else {
|
|
$auth_method = read_config_option('auth_method');
|
|
}
|
|
|
|
if ($auth_method > 0 && $user_id == 0) {
|
|
if (isset($_SESSION['sess_user_id'])) {
|
|
$user_id = $_SESSION['sess_user_id'];
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// see if permissions are simple
|
|
$simple_perms = get_simple_graph_perms($user_id);
|
|
|
|
// in case we need to review get the graph_auth_method
|
|
$graph_auth_method = read_config_option('graph_auth_method');
|
|
|
|
// get policies for all groups and user
|
|
$policies = get_policies($user_id);
|
|
|
|
if (!$simple_perms && $auth_method != 0) {
|
|
$sql_where = get_policy_where($graph_auth_method, $policies, $sql_where);
|
|
}
|
|
|
|
$tholds_sql = ("SELECT
|
|
td.*, dtd.rrd_step, tt.name AS template_name, dtr.data_source_name AS data_source,
|
|
IF(IFNULL(td.`lastread`,'') = '',NULL,(td.`lastread` + 0.0)) AS `flastread`,
|
|
IF(IFNULL(td.`oldvalue`,'') = '',NULL,(td.`oldvalue` + 0.0)) AS `foldvalue`,
|
|
UNIX_TIMESTAMP() - UNIX_TIMESTAMP(lastchanged) AS `instate`
|
|
FROM thold_data AS td
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id = td.local_graph_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id = gl.graph_template_id
|
|
LEFT JOIN host AS h
|
|
ON h.id = gl.host_id
|
|
LEFT JOIN thold_template AS tt
|
|
ON tt.id = td.thold_template_id
|
|
LEFT JOIN data_template_data AS dtd
|
|
ON dtd.local_data_id = td.local_data_id
|
|
LEFT JOIN data_template_rrd AS dtr
|
|
ON dtr.id = td.data_template_rrd_id
|
|
$sql_where
|
|
$order_by
|
|
$sql_limit");
|
|
|
|
$tholds = db_fetch_assoc($tholds_sql);
|
|
|
|
$sql = "SELECT COUNT(*)
|
|
FROM (
|
|
SELECT td.id
|
|
FROM thold_data AS td
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id=td.local_graph_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id=gl.graph_template_id
|
|
LEFT JOIN host AS h
|
|
ON h.id=gl.host_id
|
|
LEFT JOIN thold_template AS tt
|
|
ON tt.id=td.thold_template_id
|
|
$sql_where
|
|
) AS rower";
|
|
|
|
if (function_exists('get_total_row_data') && $graph_id == 0) {
|
|
$total_rows = get_total_row_data($user_id, $sql, [], 'thold', 10);
|
|
} else {
|
|
$total_rows = db_fetch_cell($sql);
|
|
}
|
|
|
|
return $tholds;
|
|
}
|
|
|
|
function get_allowed_threshold_logs($sql_where = '', $order_by = 'td.name', $sql_limit = '', &$total_rows = 0, $user_id = 0, $graph_id = 0) {
|
|
if ($sql_limit != '') {
|
|
$sql_limit = "LIMIT $sql_limit";
|
|
}
|
|
|
|
if ($order_by != '') {
|
|
$order_by = "ORDER BY $order_by";
|
|
}
|
|
|
|
if ($graph_id > 0) {
|
|
$sql_where .= (strlen($sql_where) ? ' AND ' : ' ') . " gl.id = $graph_id";
|
|
}
|
|
|
|
if (strlen($sql_where)) {
|
|
$sql_where = "WHERE $sql_where";
|
|
}
|
|
|
|
if ($user_id == -1) {
|
|
$auth_method = 0;
|
|
} else {
|
|
$auth_method = read_config_option('auth_method');
|
|
}
|
|
|
|
if ($auth_method > 0 && $user_id == 0) {
|
|
if (isset($_SESSION['sess_user_id'])) {
|
|
$user_id = $_SESSION['sess_user_id'];
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// see if permissions are simple
|
|
$simple_perms = get_simple_graph_perms($user_id);
|
|
|
|
// in case we need to review get the graph_auth_method
|
|
$graph_auth_method = read_config_option('graph_auth_method');
|
|
|
|
// get policies for all groups and user
|
|
$policies = get_policies($user_id);
|
|
|
|
if (!$simple_perms && $auth_method != 0) {
|
|
$sql_where = get_policy_where($graph_auth_method, $policies, $sql_where);
|
|
}
|
|
|
|
$tholds = db_fetch_assoc("SELECT
|
|
tl.`id`, tl.`time`, tl.`host_id`, tl.`local_graph_id`, tl.`threshold_id`,
|
|
IF(IFNULL(tl.`threshold_value`,'')='',NULL,(tl.`threshold_value` + 0.0)) AS `threshold_value`,
|
|
IF(IFNULL(tl.`current`,'')='',NULL,(tl.`current` + 0.0)) AS `current`, tl.`status`, tl.`type`,
|
|
tl.`description`, h.description AS hdescription, td.name, gtg.title_cache
|
|
FROM plugin_thold_log AS tl
|
|
INNER JOIN thold_data AS td
|
|
ON tl.threshold_id=td.id
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id=td.local_graph_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id=gl.graph_template_id
|
|
LEFT JOIN graph_templates_graph AS gtg
|
|
ON gtg.local_graph_id=gl.id
|
|
LEFT JOIN host AS h
|
|
ON h.id=gl.host_id
|
|
$sql_where
|
|
$order_by
|
|
$sql_limit");
|
|
|
|
$sql = "SELECT COUNT(*)
|
|
FROM (
|
|
SELECT tl.id
|
|
FROM plugin_thold_log AS tl
|
|
INNER JOIN thold_data AS td
|
|
ON tl.threshold_id=td.id
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id=td.local_graph_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id=gl.graph_template_id
|
|
LEFT JOIN graph_templates_graph AS gtg
|
|
ON gtg.local_graph_id=gl.id
|
|
LEFT JOIN host AS h
|
|
ON h.id=gl.host_id
|
|
$sql_where
|
|
) AS rower";
|
|
|
|
if (function_exists('get_total_row_data') && $graph_id == 0) {
|
|
$total_rows = get_total_row_data($user_id, $sql, [], 'thold_log', 10);
|
|
} else {
|
|
$total_rows = db_fetch_cell($sql);
|
|
}
|
|
|
|
return $tholds;
|
|
}
|
|
|
|
function thold_get_thold_notification_format_file($thold_id, $notify_list) {
|
|
$thold_format_file = db_fetch_cell_prepared('SELECT format_file
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$thold_id]);
|
|
|
|
$notify_format_file = '';
|
|
|
|
if ($notify_list > 0) {
|
|
$notify_format_file = db_fetch_cell_prepared('SELECT format_file
|
|
FROM plugin_notification_lists
|
|
WHERE id = ?',
|
|
[$notify_list]);
|
|
}
|
|
|
|
if ($notify_format_file != '') {
|
|
return $notify_format_file;
|
|
}
|
|
|
|
if ($thold_format_file != '') {
|
|
return $thold_format_file;
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
function thold_get_device_notification_format_file($host_id, $notify_list) {
|
|
$device_format_file = '';
|
|
|
|
if ($notify_list > 0) {
|
|
$notify_format_file = db_fetch_cell_prepared('SELECT format_file
|
|
FROM plugin_notify_list
|
|
WHERE id = ?',
|
|
[$notify_list]);
|
|
}
|
|
|
|
if ($notify_format_file != '') {
|
|
return $notify_format_file;
|
|
}
|
|
|
|
if ($device_format_file != '') {
|
|
return $device_format_file;
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
function thold_get_state_filter($state) {
|
|
$statefilter = '';
|
|
|
|
if ($state != '') {
|
|
if (get_request_var('state') == '-1') { // All
|
|
$statefilter = '';
|
|
} elseif (get_request_var('state') == '0') { // Breached or Triggered
|
|
$statefilter = '((td.thold_enabled = "on" AND td.thold_per_enabled = "on") AND
|
|
(td.thold_alert != 0 OR td.bl_alert > 0 OR ((td.thold_alert != 0 AND td.thold_fail_count >= td.thold_fail_trigger) OR (td.bl_alert > 0 AND td.bl_fail_count >= td.bl_fail_trigger))))';
|
|
} elseif (get_request_var('state') == '7') { // Disabled at Template
|
|
$statefilter = '(td.thold_enabled = "off")';
|
|
} elseif (get_request_var('state') == '2') { // Enabled
|
|
$statefilter = '(td.thold_enabled = "on" AND td.thold_per_enabled = "on")';
|
|
} elseif (get_request_var('state') == '1') { // Breached
|
|
$statefilter = '((td.thold_enabled = "on" AND td.thold_per_enabled = "on") AND (td.thold_alert != 0 OR td.bl_alert > 0))';
|
|
} elseif (get_request_var('state') == '3') { // Triggered
|
|
$statefilter = '((td.thold_enabled = "on" AND td.thold_per_enabled = "on") AND ((td.thold_alert != 0 AND td.thold_fail_count >= td.thold_fail_trigger) OR (td.bl_alert > 0 AND td.bl_fail_count >= td.bl_fail_trigger)))';
|
|
} elseif (get_request_var('state') == '4') { // Ack Required
|
|
$statefilter = '(td.acknowledgment = "on")';
|
|
} elseif (get_request_var('state') == '5') { // Disabled at Thold
|
|
$statefilter = '(td.thold_per_enabled = "")';
|
|
} elseif (get_request_var('state') == '6') { // Disabled all together
|
|
$statefilter = '(td.thold_per_enabled = "" OR td.thold_enabled = "off")';
|
|
}
|
|
}
|
|
|
|
return $statefilter;
|
|
}
|
|
|
|
function is_thold_allowed_graph($local_graph_id) {
|
|
return is_graph_allowed($local_graph_id);
|
|
}
|
|
|
|
function is_thold_allowed($id) {
|
|
$local_graph_id = db_fetch_cell_prepared('SELECT local_graph_id
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
return is_thold_allowed_graph($local_graph_id);
|
|
}
|
|
|
|
function thold_log($save) {
|
|
global $config;
|
|
|
|
include($config['base_path'] . '/plugins/thold/includes/arrays.php');
|
|
|
|
if ($save['current'] == null) {
|
|
$save['current'] = '';
|
|
}
|
|
|
|
$save['id'] = 0;
|
|
|
|
if (read_config_option('thold_log_cacti') == 'on') {
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$save['threshold_id']]);
|
|
|
|
$dt = db_fetch_cell_prepared('SELECT data_template_id
|
|
FROM data_template_data
|
|
WHERE local_data_id = ?',
|
|
[$thold['local_data_id']]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$dt]);
|
|
|
|
if ($save['type'] != 99) {
|
|
if ($save['status'] == 0) {
|
|
$desc = 'Threshold Restored ID: ' . $save['threshold_id'];
|
|
} else {
|
|
$desc = 'Threshold Breached ID: ' . $save['threshold_id'];
|
|
}
|
|
|
|
$desc .= ' DataTemplate: ' . $tname;
|
|
$desc .= ' DataSource: ' . $thold['data_source_name'];
|
|
|
|
if (isset($thold_types[$thold['thold_type']])) {
|
|
$desc .= ' Type: ' . $thold_types[$thold['thold_type']];
|
|
}
|
|
|
|
$desc .= ' Enabled: ' . ($thold['thold_enabled'] == 'on' && $thold['thold_per_enabled'] == 'on' ? 'on' : 'off');
|
|
|
|
switch ($thold['thold_type']) {
|
|
case 0:
|
|
$desc .= ' Current: ' . $save['current'];
|
|
$desc .= ' High: ' . $thold['thold_hi'];
|
|
$desc .= ' Low: ' . $thold['thold_low'];
|
|
$desc .= ' Trigger: ' . plugin_thold_duration_convert($thold['local_data_id'], $thold['thold_fail_trigger'], 'alert');
|
|
$desc .= ' Warning High: ' . $thold['thold_warning_hi'];
|
|
$desc .= ' Warning Low: ' . $thold['thold_warning_low'];
|
|
$desc .= ' Warning Trigger: ' . plugin_thold_duration_convert($thold['local_data_id'], $thold['thold_warning_fail_trigger'], 'alert');
|
|
|
|
break;
|
|
case 1:
|
|
$desc .= ' Current: ' . $save['current'];
|
|
|
|
break;
|
|
case 2:
|
|
$desc .= ' Current: ' . $save['current'];
|
|
$desc .= ' High: ' . $thold['time_hi'];
|
|
$desc .= ' Low: ' . $thold['time_low'];
|
|
$desc .= ' Trigger: ' . $thold['time_fail_trigger'];
|
|
$desc .= ' Time: ' . plugin_thold_duration_convert($thold['local_data_id'], $thold['time_fail_length'], 'time');
|
|
$desc .= ' Warning High: ' . $thold['time_warning_hi'];
|
|
$desc .= ' Warning Low: ' . $thold['time_warning_low'];
|
|
$desc .= ' Warning Trigger: ' . $thold['time_warning_fail_trigger'];
|
|
$desc .= ' Warning Time: ' . plugin_thold_duration_convert($thold['local_data_id'], $thold['time_warning_fail_length'], 'time');
|
|
|
|
break;
|
|
}
|
|
|
|
$desc .= ' SentTo: ' . (isset($save['emails']) && $save['emails'] != '' ? $save['emails'] : 'None');
|
|
$desc .= ' SendBCC: ' . (isset($save['bcc_emails']) && $save['bcc_emails'] != '' ? $save['bcc_emails'] : 'None');
|
|
} elseif (isset($save['description'])) {
|
|
$desc = $save['description'];
|
|
} else {
|
|
$desc = 'Threshold Acknowledgment';
|
|
}
|
|
|
|
if ($save['status'] == ST_RESTORAL || $save['status'] == ST_NOTIFYRS) {
|
|
thold_cacti_log($desc);
|
|
}
|
|
}
|
|
|
|
unset($save['emails']);
|
|
unset($save['bcc_emails']);
|
|
|
|
$id = sql_save($save, 'plugin_thold_log');
|
|
|
|
set_config_option('time_last_change_thold_log', time());
|
|
set_config_option('time_last_change_thold', time());
|
|
}
|
|
|
|
function plugin_thold_duration_convert($rra, $data, $type, $field = 'local_data_id') {
|
|
global $config, $repeatarray, $alertarray, $timearray;
|
|
|
|
// handle a null data value
|
|
if ($data == '') {
|
|
return '';
|
|
}
|
|
|
|
$step = db_fetch_cell_prepared("SELECT rrd_step
|
|
FROM data_template_data
|
|
WHERE $field = ?",
|
|
[$rra]);
|
|
|
|
include($config['base_path'] . '/plugins/thold/includes/arrays.php');
|
|
|
|
switch ($type) {
|
|
case 'repeat':
|
|
return (isset($repeatarray[$data]) ? $repeatarray[$data] : $data);
|
|
|
|
break;
|
|
case 'alert':
|
|
return (isset($alertarray[$data]) ? $alertarray[$data] : $data);
|
|
|
|
break;
|
|
case 'time':
|
|
return (isset($timearray[$data]) ? $timearray[$data] : $data);
|
|
|
|
break;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
function plugin_thold_log_changes($id, $changed, $message = []) {
|
|
global $config;
|
|
|
|
include($config['base_path'] . '/plugins/thold/includes/arrays.php');
|
|
|
|
$desc = '';
|
|
|
|
if (read_config_option('thold_log_changes') != 'on') {
|
|
return;
|
|
}
|
|
|
|
if (!$config['is_web']) {
|
|
$user = 'poller';
|
|
} elseif (isset($_SESSION['sess_user_id'])) {
|
|
$user = $_SESSION['sess_user_id'];
|
|
} else {
|
|
$user = 'unknown';
|
|
}
|
|
|
|
switch ($changed) {
|
|
case 'acknowledge_threshold':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc = "Threshold Acknowledged by User[$user] TH[$id]";
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
break;
|
|
case 'enabled_threshold':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc = "Threshold Enabled by User[$user] TH[$id]";
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
break;
|
|
case 'disabled_threshold':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc = "Threshold Disabled by User[$user] TH[$id]";
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
break;
|
|
case 'reapply_name':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc = "Threshold Reapply Suggested Name by User[$user] TH[$id]";
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
break;
|
|
case 'enabled_host':
|
|
$host = db_fetch_row_prepared('SELECT *
|
|
FROM host
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$desc = "Device Enabled by User[$user] Device[$id]";
|
|
|
|
break;
|
|
case 'disabled_host':
|
|
$host = db_fetch_row_prepared('SELECT *
|
|
FROM host
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$desc = "Device Disabled by User[$user] Device[$id]";
|
|
|
|
break;
|
|
case 'auto_created':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc = "Threshold Auto-created by User[$user] TH[$id]";
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
break;
|
|
case 'created':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc = "Threshold Created by User[$user] TH[$id]";
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
break;
|
|
case 'deleted':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc = "Threshold Deleted by User[$user] TH[$id]";
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
if (cacti_sizeof($message)) {
|
|
$desc .= ' Note[' . implode(', ', $message) . ']';
|
|
}
|
|
|
|
break;
|
|
case 'deleted_template':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$desc = "Template Deleted by User[$user] TH[$id]";
|
|
$desc .= ' DataTemplate[' . $thold['data_template_name'] . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
break;
|
|
case 'modified':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$rows = db_fetch_assoc_prepared('SELECT ptc.data
|
|
FROM plugin_thold_contacts AS ptc
|
|
INNER JOIN plugin_thold_threshold_contact AS pttc
|
|
WHERE ptc.id=pttc.contact_id
|
|
AND pttc.thold_id = ?',
|
|
[$id]);
|
|
|
|
$alert_emails = '';
|
|
|
|
if (read_config_option('thold_disable_legacy') != 'on') {
|
|
$alert_emails = [];
|
|
|
|
if (count($rows)) {
|
|
foreach ($rows as $row) {
|
|
$alert_emails[] = $row['data'];
|
|
}
|
|
}
|
|
|
|
$alert_emails = implode(',', $alert_emails);
|
|
|
|
if ($alert_emails != '') {
|
|
$alert_emails .= ',' . $thold['notify_extra'];
|
|
} else {
|
|
$alert_emails = $thold['notify_extra'];
|
|
}
|
|
}
|
|
|
|
$list = get_thold_notification_emails($thold['notify_alert']);
|
|
|
|
if ($list != '') {
|
|
if ($alert_emails != '') {
|
|
$alert_emails .= ',' . $list;
|
|
} else {
|
|
$alert_emails .= $list;
|
|
}
|
|
}
|
|
|
|
$warning_emails = '';
|
|
|
|
if (read_config_option('thold_disable_legacy') != 'on') {
|
|
$warning_emails = $thold['notify_warning_extra'];
|
|
}
|
|
|
|
$list = get_thold_notification_emails($thold['notify_warning']);
|
|
|
|
if ($list != '') {
|
|
if ($warning_emails != '') {
|
|
$warning_emails .= ',' . $list;
|
|
} else {
|
|
$warning_emails .= $list;
|
|
}
|
|
}
|
|
|
|
if ($message['id'] > 0) {
|
|
$desc = "Threshold Modified by User[$user] TH[$id]";
|
|
} else {
|
|
$desc = "Threshold Created by User[$user] TH[$id]";
|
|
}
|
|
|
|
$tname = db_fetch_cell_prepared('SELECT name
|
|
FROM data_template
|
|
WHERE id = ?',
|
|
[$thold['data_template_id']]);
|
|
|
|
$desc .= ' DataTemplate[' . $tname . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
if ($message['template_enabled'] == 'on') {
|
|
$desc .= ' Use Template[On]';
|
|
} else {
|
|
if (isset($thold_types[$thold['thold_type']])) {
|
|
$desc .= ' Type Type[' . $thold_types[$thold['thold_type']] . ']';
|
|
}
|
|
|
|
$desc .= ' Enabled: ' . ($thold['thold_enabled'] == 'on' && $thold['thold_per_enabled'] == 'on' ? 'on' : 'off');
|
|
|
|
switch ($message['thold_type']) {
|
|
case 0:
|
|
$desc .= ' High[' . $message['thold_hi'] . ']';
|
|
$desc .= ' Low[' . $message['thold_low'] . ']';
|
|
$desc .= ' Trigger[' . plugin_thold_duration_convert($thold['local_data_id'], $message['thold_fail_trigger'], 'alert') . ']';
|
|
$desc .= ' WarnHigh[' . $message['thold_warning_hi'] . ']';
|
|
$desc .= ' WarnLow[' . $message['thold_warning_low'] . ']';
|
|
$desc .= ' WarnTrigger[' . plugin_thold_duration_convert($thold['local_data_id'], $message['thold_warning_fail_trigger'], 'alert') . ']';
|
|
|
|
break;
|
|
case 1:
|
|
$desc .= ' BL Type[' . (!isset($message['bl_type']) ? 0 : $message['bl_type']) . ']';
|
|
|
|
if ($message['bl_type'] == 1) {
|
|
$desc .= ' BL CF[' . (!isset($message['bl_cf']) ? 'AVG' : $message['bl_cf']) . ']';
|
|
}
|
|
|
|
$desc .= ' Range[' . $message['bl_ref_time_range'] . ']';
|
|
$desc .= ' DevUp[' . $message['bl_pct_up'] . ']';
|
|
$desc .= ' DevDown[' . $message['bl_pct_down'] . ']';
|
|
$desc .= ' Trigger[' . $message['bl_fail_trigger'] . ']';
|
|
|
|
break;
|
|
case 2:
|
|
$desc .= ' High[' . $message['time_hi'] . ']';
|
|
$desc .= ' Low[' . $message['time_low'] . ']';
|
|
$desc .= ' Trigger[' . $message['time_fail_trigger'] . ']';
|
|
$desc .= ' Time: ' . plugin_thold_duration_convert($thold['local_data_id'], $message['time_fail_length'], 'time') . ']';
|
|
$desc .= ' WarnHigh[' . $message['time_warning_hi'] . ']';
|
|
$desc .= ' WarnLow[' . $message['time_warning_low'] . ']';
|
|
$desc .= ' WarnTrigger[' . $message['time_warning_fail_trigger'] . ']';
|
|
$desc .= ' WarnTime[' . plugin_thold_duration_convert($thold['local_data_id'], $message['time_warning_fail_length'], 'time') . ']';
|
|
|
|
break;
|
|
}
|
|
|
|
$desc .= ' CDEF[' . $message['cdef'] . ']';
|
|
$desc .= ' ReAlert[' . plugin_thold_duration_convert($thold['local_data_id'], $message['repeat_alert'], 'alert') . ']';
|
|
$desc .= ' AlertEmails[' . $alert_emails . ']';
|
|
$desc .= ' WarnEmails[' . $warning_emails . ']';
|
|
}
|
|
|
|
break;
|
|
case 'modified_template':
|
|
$thold = db_fetch_row_prepared('SELECT *
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
$rows = db_fetch_assoc_prepared('SELECT ptc.data
|
|
FROM plugin_thold_contacts AS ptc
|
|
INNER JOIN plugin_thold_template_contact AS pttc
|
|
ON ptc.id=pttc.contact_id
|
|
WHERE pttc.template_id = ?',
|
|
[$id]);
|
|
|
|
$alert_emails = '';
|
|
|
|
if (read_config_option('thold_disable_legacy') != 'on') {
|
|
$alert_emails = [];
|
|
|
|
if (count($rows)) {
|
|
foreach ($rows as $row) {
|
|
$alert_emails[] = $row['data'];
|
|
}
|
|
}
|
|
|
|
$alert_emails = implode(',', $alert_emails);
|
|
|
|
if ($alert_emails != '') {
|
|
$alert_emails .= ',' . $thold['notify_extra'];
|
|
} else {
|
|
$alert_emails = $thold['notify_extra'];
|
|
}
|
|
}
|
|
|
|
$list = get_thold_notification_emails($thold['notify_alert']);
|
|
|
|
if ($list != '') {
|
|
if ($alert_emails != '') {
|
|
$alert_emails .= ',' . $list;
|
|
} else {
|
|
$alert_emails .= $list;
|
|
}
|
|
}
|
|
|
|
$warning_emails = '';
|
|
|
|
if (read_config_option('thold_disable_legacy') != 'on') {
|
|
$warning_emails = $thold['notify_warning_extra'];
|
|
}
|
|
|
|
$list = get_thold_notification_emails($thold['notify_warning']);
|
|
|
|
if ($list != '') {
|
|
if ($warning_emails != '') {
|
|
$warning_emails .= ',' . $list;
|
|
} else {
|
|
$warning_emails .= $list;
|
|
}
|
|
}
|
|
|
|
if ($message['id'] > 0) {
|
|
$desc = "Template Modified by User[$user] TT[$id]";
|
|
} else {
|
|
$desc = "Template Created by User[$user] TT[$id]";
|
|
}
|
|
|
|
$desc .= ' DataTemplate[' . $thold['data_template_name'] . ']';
|
|
$desc .= ' DataSource[' . $thold['data_source_name'] . ']';
|
|
|
|
if (isset($thold_types[$thold['thold_type']])) {
|
|
$desc .= ' Thold Type[' . $thold_types[$message['thold_type']] . ']';
|
|
}
|
|
|
|
$desc .= ' Enabled: ' . ($thold['thold_enabled'] == 'on' ? 'on' : 'off');
|
|
|
|
switch ($message['thold_type']) {
|
|
case 0:
|
|
$desc .= ' High[' . (isset($message['thold_hi']) ? $message['thold_hi'] : '') . ']';
|
|
$desc .= ' Low[' . (isset($message['thold_low']) ? $message['thold_low'] : '') . ']';
|
|
$desc .= ' Trigger[' . plugin_thold_duration_convert($thold['data_template_id'], (isset($message['thold_fail_trigger']) ? $message['thold_fail_trigger'] : ''), 'alert', 'data_template_id') . ']';
|
|
$desc .= ' WarnHigh[' . (isset($message['thold_warning_hi']) ? $message['thold_warning_hi'] : '') . ']';
|
|
$desc .= ' WarnLow[' . (isset($message['thold_warning_low']) ? $message['thold_warning_low'] : '') . ']';
|
|
$desc .= ' WarnTrigger[' . plugin_thold_duration_convert($thold['data_template_id'], (isset($message['thold_warning_fail_trigger']) ? $message['thold_fail_trigger'] : ''), 'alert', 'data_template_id') . ']';
|
|
|
|
break;
|
|
case 1:
|
|
$desc .= ' BL Type[' . (!isset($message['bl_type']) ? 0 : $message['bl_type']) . ']';
|
|
|
|
if ($message['bl_type'] == 1) {
|
|
$desc .= ' BL CF[' . (!isset($message['bl_cf']) ? 'AVG' : $message['bl_cf']) . ']';
|
|
}
|
|
|
|
$desc .= ' Range[' . $message['bl_ref_time_range'] . ']';
|
|
$desc .= ' DevUp[' . (isset($message['bl_pct_up']) ? $message['bl_pct_up'] : '') . ']';
|
|
$desc .= ' DevDown[' . (isset($message['bl_pct_down']) ? $message['bl_pct_down'] : '') . ']';
|
|
$desc .= ' Trigger[' . $message['bl_fail_trigger'] . ']';
|
|
|
|
break;
|
|
case 2:
|
|
$desc .= ' High[' . $message['time_hi'] . ']';
|
|
$desc .= ' Low[' . $message['time_low'] . ']';
|
|
$desc .= ' Trigger[' . $message['time_fail_trigger'] . ']';
|
|
$desc .= ' Time[' . plugin_thold_duration_convert($thold['data_template_id'], $message['time_fail_length'], 'alert', 'data_template_id') . ']';
|
|
$desc .= ' WarnHigh[' . $message['time_warning_hi'] . ']';
|
|
$desc .= ' WarnLow[' . $message['time_warning_low'] . ']';
|
|
$desc .= ' WarnTrigger[' . $message['time_warning_fail_trigger'] . ']';
|
|
$desc .= ' WarnTime[' . plugin_thold_duration_convert($thold['data_template_id'], $message['time_warning_fail_length'], 'alert', 'data_template_id') . ']';
|
|
|
|
break;
|
|
}
|
|
|
|
$desc .= ' CDEF[' . (isset($message['cdef']) ? $message['cdef'] : '') . ']';
|
|
$desc .= ' ReAlert[' . plugin_thold_duration_convert($thold['data_template_id'], $message['repeat_alert'], 'alert', 'data_template_id') . ']';
|
|
$desc .= ' AlertEmails[' . $alert_emails . ']';
|
|
$desc .= ' WarnEmails[' . $warning_emails . ']';
|
|
|
|
break;
|
|
}
|
|
|
|
if ($desc != '') {
|
|
thold_cacti_log($desc);
|
|
}
|
|
}
|
|
|
|
function get_thold_severity(&$td) {
|
|
$severity = THOLD_SEVERITY_NORMAL;
|
|
|
|
if (($td['template_enabled'] == 'on' && $td['thold_enabled'] == 'off') || $td['thold_per_enabled'] == '') {
|
|
return THOLD_SEVERITY_DISABLED;
|
|
}
|
|
|
|
if (!isset($td['thold_type'])) {
|
|
return THOLD_SEVERITY_NORMAL;
|
|
}
|
|
|
|
switch($td['thold_type']) {
|
|
case '0': // Hi/Low
|
|
if ($td['thold_alert'] != 0) {
|
|
if ($td['thold_hi'] != '' || $td['thold_low'] != '') {
|
|
if ($td['thold_fail_count'] >= $td['thold_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_ALERT;
|
|
} elseif ($td['lastread'] > $td['thold_hi'] && $td['thold_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_ALERT;
|
|
} elseif ($td['lastread'] < $td['thold_low'] && $td['thold_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_ALERT;
|
|
} elseif ($td['thold_warning_hi'] != '' || $td['thold_warning_low'] != '') {
|
|
if ($td['thold_warning_fail_count'] >= $td['thold_warning_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] > $td['thold_warning_hi'] && $td['thold_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] < $td['thold_warning_low'] && $td['thold_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
} elseif ($td['thold_warning_hi'] != '' || $td['thold_warning_low'] != '') {
|
|
if ($td['thold_warning_fail_count'] >= $td['thold_warning_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] > $td['thold_warning_hi'] && $td['thold_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] < $td['thold_warning_low'] && $td['thold_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
}
|
|
} elseif ($td['acknowledgment'] == 'on') {
|
|
$severity = THOLD_SEVERITY_ACKREQ;
|
|
}
|
|
|
|
break;
|
|
case '1': // Baseline
|
|
if ($td['bl_alert'] == 1) {
|
|
if ($td['bl_fail_count'] >= $td['bl_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_BASELINE;
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
} elseif ($td['bl_alert'] == 2) {
|
|
if ($td['bl_fail_count'] >= $td['bl_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_BASELINE;
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
} elseif ($td['acknowledgment'] == 'on') {
|
|
$severity = THOLD_SEVERITY_ACKREQ;
|
|
}
|
|
|
|
break;
|
|
case '2': // Time Based
|
|
if ($td['thold_alert'] != 0) {
|
|
if ($td['time_hi'] != '' || $td['time_low'] != '') {
|
|
if ($td['thold_fail_count'] >= $td['time_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_ALERT;
|
|
} elseif ($td['lastread'] > $td['time_hi'] && $td['time_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_ALERT;
|
|
} elseif ($td['lastread'] < $td['time_low'] && $td['time_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_ALERT;
|
|
} elseif ($td['time_warning_hi'] != '' || $td['time_warning_low']) {
|
|
if ($td['thold_warning_fail_count'] >= $td['time_warning_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] > $td['time_warning_hi'] && $td['time_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] < $td['time_warning_low'] && $td['time_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
} elseif ($td['time_warning_hi'] != '' || $td['time_warning_low']) {
|
|
if ($td['thold_warning_fail_count'] >= $td['time_warning_fail_trigger']) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] > $td['time_warning_hi'] && $td['time_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} elseif ($td['lastread'] < $td['time_warning_low'] && $td['time_warning_fail_trigger'] == 0) {
|
|
$severity = THOLD_SEVERITY_WARNING;
|
|
} else {
|
|
$severity = THOLD_SEVERITY_NOTICE;
|
|
}
|
|
}
|
|
} elseif ($td['acknowledgment'] == 'on') {
|
|
$severity = THOLD_SEVERITY_ACKREQ;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return $severity;
|
|
}
|
|
|
|
function thold_datasource_required($name, $data_source) {
|
|
$show_datasource = read_config_option('show_datasource');
|
|
|
|
if ($show_datasource == 'on') {
|
|
if (strstr($name, "[$data_source]") !== false) {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function thold_check_threshold(&$thold_data) {
|
|
global $config, $plugins, $debug;
|
|
|
|
// Modify critical thold values based upon a cdef if present
|
|
thold_modify_values_by_cdef($thold_data);
|
|
|
|
thold_debug('Checking Threshold:' .
|
|
' id: ' . var_export($thold_data['id'], true) .
|
|
', name: ' . var_export($thold_data['name_cache'], true) .
|
|
', data source: ' . var_export($thold_data['data_source_name'], true) .
|
|
', local_data_id: ' . var_export($thold_data['local_data_id'], true) .
|
|
', data_template_rrd_id: ' . var_export($thold_data['data_template_rrd_id'], true) .
|
|
', value: ' . var_export($thold_data['lastread'], true));
|
|
|
|
// Do not proceed if we have chosen to globally disable all alerts
|
|
if (read_config_option('thold_disable_all') == 'on') {
|
|
thold_debug('Threshold checking is disabled globally');
|
|
|
|
return;
|
|
}
|
|
|
|
$alert_exempt = read_config_option('alert_exempt');
|
|
// check for exemptions
|
|
$weekday = date('l');
|
|
|
|
if (($weekday == 'Saturday' || $weekday == 'Sunday') && $alert_exempt == 'on') {
|
|
thold_debug('Threshold checking is disabled by global weekend exemption');
|
|
|
|
return;
|
|
}
|
|
|
|
// check for the weekend exemption on the threshold level
|
|
if (($weekday == 'Saturday' || $weekday == 'Sunday') && $thold_data['exempt'] == 'on') {
|
|
thold_debug('Threshold checking is disabled by global weekend exemption');
|
|
|
|
return;
|
|
}
|
|
|
|
// don't alert for this host if it's selected for maintenance
|
|
if (api_plugin_is_enabled('maint') || in_array('maint', $plugins, true)) {
|
|
include_once($config['base_path'] . '/plugins/maint/functions.php');
|
|
}
|
|
|
|
if (api_plugin_is_enabled('maint') && plugin_maint_check_cacti_host($thold_data['host_id'])) {
|
|
$maint_dev = true;
|
|
} else {
|
|
$maint_dev = false;
|
|
}
|
|
|
|
$local_graph_id = $thold_data['local_graph_id'];
|
|
|
|
$h = [];
|
|
|
|
if (isset($thold_data['host_id']) && $thold_data['host_id'] > 0) {
|
|
// only alert if Device is in UP mode (not down, unknown, or recovering)
|
|
$h = db_fetch_row_prepared('SELECT *
|
|
FROM host
|
|
WHERE id = ?',
|
|
[$thold_data['host_id']]);
|
|
|
|
if (cacti_sizeof($h) && $h['status'] != 3) {
|
|
thold_debug('Threshold checking halted by Device Status (' . $h['status'] . ')');
|
|
|
|
return;
|
|
}
|
|
|
|
$h['thold_id'] = $thold_data['id'];
|
|
} else {
|
|
// function called during polling
|
|
$h['id'] = $thold_data['host_id'];
|
|
$h['snmp_engine_id'] = $thold_data['snmp_engine_id'];
|
|
$h['description'] = $thold_data['description'];
|
|
$h['hostname'] = $thold_data['hostname'];
|
|
$h['thold_id'] = $thold_data['id'];
|
|
}
|
|
|
|
// ensure that Cacti will make of individual defined SNMP Engine IDs
|
|
$overwrite['snmp_engine_id'] = $h['snmp_engine_id'];
|
|
|
|
// pull a few default settings
|
|
$global_alert_address = read_config_option('alert_email');
|
|
|
|
// Settings for syslogging
|
|
$syslog = $thold_data['syslog_enabled'] == 'on' ? true : false;
|
|
$syslog_priority = $thold_data['syslog_priority'];
|
|
$syslog_facility = $thold_data['syslog_facility'];
|
|
|
|
$deadnotify = (read_config_option('alert_deadnotify') == 'on');
|
|
$realert = read_config_option('alert_repeat');
|
|
$alert_trigger = read_config_option('alert_trigger');
|
|
$alert_bl_trigger = read_config_option('alert_bl_trigger');
|
|
$httpurl = read_config_option('base_url');
|
|
$thold_send_text_only = read_config_option('thold_send_text_only');
|
|
|
|
$thold_snmp_traps = (read_config_option('thold_alert_snmp') == 'on');
|
|
$thold_snmp_warning_traps = (read_config_option('thold_alert_snmp_warning') != 'on');
|
|
$thold_snmp_normal_traps = (read_config_option('thold_alert_snmp_normal') != 'on');
|
|
$cacti_polling_interval = read_config_option('poller_interval');
|
|
|
|
// remove this after adding an option for it
|
|
$show_datasource = thold_datasource_required(thold_get_cached_name($thold_data), $thold_data['data_source_name']);
|
|
|
|
$trigger = ($thold_data['thold_fail_trigger'] == '' ? $alert_trigger : $thold_data['thold_fail_trigger']);
|
|
$warning_trigger = ($thold_data['thold_warning_fail_trigger'] == '' ? $alert_trigger : $thold_data['thold_warning_fail_trigger']);
|
|
$alertstat = $thold_data['thold_alert'];
|
|
|
|
// see if we have two notification lists or one
|
|
$notify_different = false;
|
|
|
|
if ($thold_data['notify_warning'] > 0) {
|
|
if ($thold_data['notify_warning'] != $thold_data['notify_alert']) {
|
|
if (read_config_option('thold_notify_alerts_to_warning_recipients') == 'on') {
|
|
$notify_different = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// setup base units
|
|
$baseu = db_fetch_cell_prepared('SELECT base_value
|
|
FROM graph_templates_graph
|
|
WHERE local_graph_id = ?',
|
|
[$thold_data['local_graph_id']]);
|
|
|
|
if ($thold_data['data_type'] == 2) {
|
|
$suffix = false;
|
|
} else {
|
|
$suffix = true;
|
|
}
|
|
|
|
$show_units = ($thold_data['show_units'] ? true : false);
|
|
$units_suffix = $thold_data['units_suffix'];
|
|
$decimals = $thold_data['decimals'] >= 0 ? $thold_data['decimals'] : 2;
|
|
|
|
$file_array = [];
|
|
|
|
if ($thold_send_text_only != 'on') {
|
|
if (!empty($thold_data['local_graph_id'])) {
|
|
$file_array = [
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'local_data_id' => $thold_data['local_data_id'],
|
|
'rra_id' => 0,
|
|
'file' => "$httpurl/graph_image.php?local_graph_id=" . $thold_data['local_graph_id'] . '&rra_id=0&view_type=tree',
|
|
'mimetype' => 'image/png',
|
|
'filename' => clean_up_name(thold_get_cached_name($thold_data))
|
|
];
|
|
}
|
|
}
|
|
|
|
$url = $httpurl . '/graph.php?local_graph_id=' . $thold_data['local_graph_id'] . '&rra_id=all';
|
|
$lastread = $thold_data['lastread'];
|
|
|
|
$alert_emails = get_thold_emails($thold_data, 'alert', 'to');
|
|
$alert_bcc_emails = get_thold_emails($thold_data, 'alert', 'bcc');
|
|
$warning_emails = get_thold_emails($thold_data, 'warning', 'to');
|
|
$warning_bcc_emails = get_thold_emails($thold_data, 'warning', 'bcc');
|
|
|
|
switch ($thold_data['thold_type']) {
|
|
case 0: // hi/low
|
|
if (is_numeric($thold_data['lastread'])) {
|
|
$breach_up = ($thold_data['thold_hi'] != '' && $thold_data['lastread'] > $thold_data['thold_hi']);
|
|
$breach_down = ($thold_data['thold_low'] != '' && $thold_data['lastread'] < $thold_data['thold_low']);
|
|
$warning_breach_up = ($thold_data['thold_warning_hi'] != '' && $thold_data['lastread'] > $thold_data['thold_warning_hi']);
|
|
$warning_breach_down = ($thold_data['thold_warning_low'] != '' && $thold_data['lastread'] < $thold_data['thold_warning_low']);
|
|
} else {
|
|
$breach_up = $breach_down = $warning_breach_up = $warning_breach_down = false;
|
|
}
|
|
|
|
// is in alert status
|
|
if ($breach_up || $breach_down) {
|
|
$notify = false;
|
|
|
|
thold_debug('Threshold HI / Low check breached HI:' . $thold_data['thold_hi'] . ' LOW:' . $thold_data['thold_low'] . ' VALUE:' . $thold_data['lastread']);
|
|
|
|
if (!$maint_dev) {
|
|
$thold_data['thold_fail_count']++;
|
|
}
|
|
|
|
$thold_data['thold_alert'] = ($breach_up ? STAT_HI : STAT_LO);
|
|
|
|
// Re-Alert?
|
|
$ra = ($thold_data['thold_fail_count'] > $trigger && $thold_data['repeat_alert'] != 0 && $thold_data['thold_fail_count'] % $thold_data['repeat_alert'] == 0);
|
|
|
|
if (($thold_data['thold_fail_count'] == $trigger || $ra) && !$maint_dev) {
|
|
$notify = true;
|
|
}
|
|
|
|
if ($notify && !$ra) {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET lastchanged = NOW()
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
|
|
if ($thold_data['persist_ack'] == 'on' || $thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = "on"
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
}
|
|
|
|
// If this is a realert and the operator has reset the ack, don't notify
|
|
if ($notify && $ra && $thold_data['reset_ack'] == 'on' && $thold_data['acknowledgment'] == '') {
|
|
$suspend_notify = true;
|
|
} else {
|
|
$suspend_notify = false;
|
|
}
|
|
|
|
$subject = get_email_subject('ALERT', false, $lastread, $ra, $breach_up, $thold_data);
|
|
|
|
if ($notify) {
|
|
if (!$suspend_notify && !$maint_dev) {
|
|
thold_debug('Alerting is necessary');
|
|
|
|
$notify_list_id = $thold_data['notify_alert'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
if (trim($alert_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_alert_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($alert_emails, $alert_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
|
|
if ($notify_different) {
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
}
|
|
|
|
thold_command_execution($thold_data, $h, $breach_up, $breach_down);
|
|
|
|
$save = [
|
|
'class' => 'alert',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'repeat_alert' => $ra,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 3;
|
|
$thold_snmp_data['eventSeverity'] = $thold_data['snmp_event_severity'];
|
|
$thold_snmp_data['eventStatus'] = $thold_data['thold_alert'] + 1;
|
|
$thold_snmp_data['eventRealertStatus'] = ($ra ? ($breach_up ? 3 : 2) : 1);
|
|
$thold_snmp_data['eventNotificationType'] = ($ra ? ST_NOTIFYRA : ST_NOTIFYAL) + 1;
|
|
$thold_snmp_data['eventFailCount'] = $thold_data['thold_fail_count'];
|
|
$thold_snmp_data['eventFailDuration'] = $thold_data['thold_fail_count'] * $cacti_polling_interval;
|
|
$thold_snmp_data['eventFailDurationTrigger'] = $trigger * $cacti_polling_interval;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
$thold_snmp_data['eventDescription'] = str_replace(
|
|
['<FAIL_COUNT>', '<FAIL_DURATION>'],
|
|
[$thold_snmp_data['eventFailCount'], $thold_snmp_data['eventFailDuration']],
|
|
$thold_snmp_data['eventDescription']
|
|
);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 0,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($breach_up ? $thold_data['thold_hi'] : $thold_data['thold_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ($ra ? ST_NOTIFYRA : ST_NOTIFYAL),
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
}
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = ?,
|
|
thold_fail_count = ?,
|
|
thold_warning_fail_count = 0
|
|
WHERE id = ?',
|
|
[$thold_data['thold_alert'], $thold_data['thold_fail_count'], $thold_data['id']]);
|
|
} elseif ($warning_breach_up || $warning_breach_down) {
|
|
$notify = false;
|
|
|
|
thold_debug('Threshold HI / Low Warning check breached HI:' . $thold_data['thold_warning_hi'] .
|
|
' LOW:' . $thold_data['thold_warning_low'] .
|
|
' VALUE:' . $thold_data['lastread'] .
|
|
' TRIGGER:' . $trigger .
|
|
' WRNCNT:' . $thold_data['thold_warning_fail_count']);
|
|
|
|
if (!$maint_dev) {
|
|
$thold_data['thold_warning_fail_count']++;
|
|
}
|
|
|
|
$thold_data['thold_alert'] = ($warning_breach_up ? STAT_HI : STAT_LO);
|
|
|
|
// re-alert?
|
|
$ra = ($thold_data['thold_warning_fail_count'] > $warning_trigger && $thold_data['repeat_alert'] != 0 && $thold_data['thold_warning_fail_count'] % $thold_data['repeat_alert'] == 0);
|
|
|
|
if (($thold_data['thold_warning_fail_count'] == $warning_trigger || $ra) && !$maint_dev) {
|
|
$notify = true;
|
|
}
|
|
|
|
if ($notify && !$ra) {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET lastchanged = NOW()
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
|
|
if ($thold_data['persist_ack'] == 'on' || $thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = "on"
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
}
|
|
|
|
// If this is a realert and the operator has reset the ack, don't notify
|
|
if ($notify && $ra && $thold_data['reset_ack'] == 'on' && $thold_data['acknowledgment'] == '') {
|
|
$suspend_notify = true;
|
|
} else {
|
|
$suspend_notify = false;
|
|
}
|
|
|
|
if ($notify) {
|
|
$etrigger = false;
|
|
} else {
|
|
$etrigger = true;
|
|
}
|
|
|
|
$subject = get_email_subject('WARNING', $etrigger, $lastread, $ra, $warning_breach_up, $thold_data);
|
|
|
|
if ($notify) {
|
|
if (!$suspend_notify && !$maint_dev) {
|
|
thold_debug('Alerting is necessary');
|
|
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_warning_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
$save = [
|
|
'class' => 'warn',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'repeat_alert' => $ra,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_warning_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 2;
|
|
$thold_snmp_data['eventSeverity'] = $thold_data['snmp_event_warning_severity'];
|
|
$thold_snmp_data['eventStatus'] = $thold_data['thold_alert'] + 1;
|
|
$thold_snmp_data['eventRealertStatus'] = ($ra ? ($warning_breach_up ? 3 : 2) : 1);
|
|
$thold_snmp_data['eventNotificationType'] = ($ra ? ST_NOTIFYRAW : ST_NOTIFYWA) + 1;
|
|
$thold_snmp_data['eventFailCount'] = $thold_data['thold_warning_fail_count'];
|
|
$thold_snmp_data['eventFailDuration'] = $thold_data['thold_warning_fail_count'] * $cacti_polling_interval;
|
|
$thold_snmp_data['eventFailDurationTrigger'] = $warning_trigger * $cacti_polling_interval;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
$thold_snmp_data['eventDescription'] = str_replace(
|
|
['<FAIL_COUNT>', '<FAIL_DURATION>'],
|
|
[$thold_snmp_data['eventFailCount'], $thold_snmp_data['eventFailDuration']],
|
|
$thold_snmp_data['eventDescription']
|
|
);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 0,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($warning_breach_up ? $thold_data['thold_warning_hi'] : $thold_data['thold_warning_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ($ra ? ST_NOTIFYRAW : ST_NOTIFYWA),
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
} elseif (($thold_data['thold_warning_fail_count'] >= $warning_trigger) && ($thold_data['thold_fail_count'] >= $trigger)) {
|
|
$subject = get_email_subject('ALERT > WARNING', false, $lastread, $ra, $warning_breach_up, $thold_data);
|
|
|
|
if (!$suspend_notify && !$maint_dev) {
|
|
$notify_list_id = $thold_data['notify_alert'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($alert_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_warning_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($alert_emails, $alert_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
if ($notify_different) {
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
}
|
|
|
|
$save = [
|
|
'class' => 'alert2warn',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'repeat_alert' => $ra,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_warning_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 2;
|
|
$thold_snmp_data['eventSeverity'] = $thold_data['snmp_event_warning_severity'];
|
|
$thold_snmp_data['eventStatus'] = $thold_data['thold_alert'] + 1;
|
|
$thold_snmp_data['eventNotificationType'] = ST_NOTIFYAW + 1;
|
|
$thold_snmp_data['eventFailCount'] = $thold_data['thold_warning_fail_count'];
|
|
$thold_snmp_data['eventFailDuration'] = $thold_data['thold_warning_fail_count'] * $cacti_polling_interval;
|
|
$thold_snmp_data['eventFailDurationTrigger'] = $trigger * $cacti_polling_interval;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
$thold_snmp_data['eventDescription'] = str_replace(
|
|
['<FAIL_COUNT>', '<FAIL_DURATION>'],
|
|
[$thold_snmp_data['eventFailCount'], $thold_snmp_data['eventFailDuration']],
|
|
$thold_snmp_data['eventDescription']
|
|
);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 0,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($warning_breach_up ? $thold_data['thold_warning_hi'] : $thold_data['thold_warning_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_NOTIFYAW,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
}
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = ?,
|
|
thold_warning_fail_count = ?,
|
|
thold_fail_count = 0
|
|
WHERE id = ?',
|
|
[$thold_data['thold_alert'], $thold_data['thold_warning_fail_count'], $thold_data['id']]);
|
|
} else {
|
|
thold_debug('Threshold HI / Low check is Normal HI:' . $thold_data['thold_hi'] . ' LOW:' . $thold_data['thold_low'] . ' VALUE:' . $thold_data['lastread']);
|
|
|
|
$subject = get_email_subject('NORMAL', false, $lastread, false, false, $thold_data);
|
|
|
|
// if we were at an alert status before
|
|
if ($alertstat != 0) {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = 0,
|
|
thold_fail_count = 0,
|
|
lastchanged = NOW(),
|
|
thold_warning_fail_count=0
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
|
|
if ($thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment=""
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
|
|
if ($thold_data['thold_warning_fail_count'] >= $warning_trigger && $thold_data['restored_alert'] != 'on' && !$maint_dev) {
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['restored_alert'] != 'on' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_restoral_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
$save = [
|
|
'class' => 'warn2normal',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_normal_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 1;
|
|
$thold_snmp_data['eventSeverity'] = 1;
|
|
$thold_snmp_data['eventStatus'] = 1;
|
|
$thold_snmp_data['eventNotificationType'] = ST_NOTIFYRS + 1;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 0,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => '',
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_NOTIFYRS,
|
|
'description' => $subject,
|
|
'emails' => $warning_emails,
|
|
'bcc_emails' => $warning_bcc_emails]
|
|
);
|
|
} elseif ($thold_data['thold_fail_count'] >= $trigger && $thold_data['restored_alert'] != 'on' && !$maint_dev) {
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_alert'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($alert_emails) != '' && $thold_data['restored_alert'] != 'on' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_restoral_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($alert_emails, $alert_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
if ($notify_different) {
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
}
|
|
|
|
thold_command_execution($thold_data, $h, false, false, true);
|
|
|
|
$save = [
|
|
'class' => 'alert2normal',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_normal_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 1;
|
|
$thold_snmp_data['eventSeverity'] = 1;
|
|
$thold_snmp_data['eventStatus'] = 1;
|
|
$thold_snmp_data['eventNotificationType'] = ST_NOTIFYRS + 1;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 0,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => '',
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_NOTIFYRS,
|
|
'description' => $subject,
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
}
|
|
|
|
if ($maint_dev) {
|
|
thold_log([
|
|
'type' => 0,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => '',
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_NOTIFYRS,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
case 1: // baseline
|
|
$bl_alert_prev = $thold_data['bl_alert'];
|
|
$bl_count_prev = $thold_data['bl_fail_count'];
|
|
$bl_fail_trigger = ($thold_data['bl_fail_trigger'] == '' ? $alert_bl_trigger : $thold_data['bl_fail_trigger']);
|
|
|
|
$thold_data['bl_alert'] = thold_check_baseline($thold_data['local_data_id'], $thold_data['data_source_name'], $thold_data['lastread'], $thold_data);
|
|
|
|
switch($thold_data['bl_alert']) {
|
|
case -2: // exception is active, Future Release 'todo'
|
|
break;
|
|
case -1: // reference value not available, Future Release 'todo'
|
|
break;
|
|
case 0: // all clear
|
|
// if we were at an alert status before
|
|
if ($bl_alert_prev != 0) {
|
|
thold_debug('Threshold Baseline check is Normal');
|
|
|
|
$subject = get_email_subject('NORMAL', false, $lastread, false, false, $thold_data);
|
|
|
|
if ($thold_data['bl_fail_count'] >= $bl_fail_trigger && $thold_data['restored_alert'] != 'on' && !$maint_dev) {
|
|
thold_debug('Threshold Baseline check returned to normal');
|
|
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_alert'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($alert_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_restoral_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($alert_emails, $alert_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
if ($notify_different) {
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
}
|
|
|
|
thold_command_execution($thold_data, $h, false, false, true);
|
|
|
|
$save = [
|
|
'class' => 'blnormal',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'host_data' => $h
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_normal_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 1;
|
|
$thold_snmp_data['eventSeverity'] = 1;
|
|
$thold_snmp_data['eventStatus'] = 1;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
|
|
$thold_snmp_data['eventNotificationType'] = ST_NOTIFYRS + 1;
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
|
|
if ($thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = ""
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
|
|
// Set the return to normal time
|
|
db_execute_prepared('UPDATE thold_data SET lastchanged = NOW() WHERE id = ?', [$thold_data['id']]);
|
|
|
|
thold_log([
|
|
'type' => 1,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => '',
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_RESTORAL,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
}
|
|
}
|
|
|
|
$thold_data['bl_fail_count'] = 0;
|
|
|
|
break;
|
|
case 1: // value is below calculated threshold
|
|
case 2: // value is above calculated threshold
|
|
if (!$maint_dev) {
|
|
$thold_data['bl_fail_count']++;
|
|
}
|
|
|
|
$breach_up = ($thold_data['bl_alert'] == STAT_HI);
|
|
$breach_down = ($thold_data['bl_alert'] == STAT_LO);
|
|
|
|
thold_debug('Threshold Baseline check breached');
|
|
|
|
// re-alert?
|
|
$ra_modulo = ($thold_data['repeat_alert'] == '' ? $realert : $thold_data['repeat_alert']);
|
|
|
|
$ra = ($thold_data['bl_fail_count'] > $bl_fail_trigger && !empty($ra_modulo) && ($thold_data['bl_fail_count'] % $ra_modulo) == 0);
|
|
|
|
if ($thold_data['bl_fail_count'] == $bl_fail_trigger || $ra) {
|
|
if (!$ra) {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET lastchanged = NOW()
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
|
|
if ($thold_data['persist_ack'] == 'on' || $thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = "on"
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
}
|
|
|
|
// If this is a realert and the operator has reset the ack, don't notify
|
|
if ($ra && $thold_data['reset_ack'] == 'on' && $thold_data['acknowledgment'] == '') {
|
|
$suspend_notify = true;
|
|
} else {
|
|
$suspend_notify = false;
|
|
}
|
|
|
|
$subject = get_email_subject('ALERT', false, $lastread, $ra, $breach_up, $thold_data);
|
|
|
|
if (!$suspend_notify && !$maint_dev) {
|
|
thold_debug('Alerting is necessary');
|
|
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_alert'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($alert_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_alert_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($alert_emails, $alert_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
if ($notify_different) {
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
}
|
|
|
|
thold_command_execution($thold_data, $h, $breach_up, $breach_down, false);
|
|
|
|
$save = [
|
|
'class' => 'blalert',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'repeat_alert' => $ra,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 3;
|
|
$thold_snmp_data['eventSeverity'] = $thold_data['snmp_event_severity'];
|
|
$thold_snmp_data['eventStatus'] = $thold_data['bl_alert'] + 1;
|
|
$thold_snmp_data['eventRealertStatus'] = ($ra ? ($breach_up ? 3 : 2) : 1);
|
|
$thold_snmp_data['eventNotificationType'] = ($ra ? ST_NOTIFYRA : ST_NOTIFYAL) + 1;
|
|
$thold_snmp_data['eventFailCount'] = $thold_data['bl_fail_count'];
|
|
$thold_snmp_data['eventFailDuration'] = $thold_data['bl_fail_count'] * $cacti_polling_interval;
|
|
$thold_snmp_data['eventFailCountTrigger'] = $bl_fail_trigger;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
$thold_snmp_data['eventDescription'] = str_replace(
|
|
['<FAIL_COUNT>', '<FAIL_DURATION>'],
|
|
[$thold_snmp_data['eventFailCount'], $thold_snmp_data['eventFailDuration']],
|
|
$thold_snmp_data['eventDescription']
|
|
);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 1,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($breach_up ? $thold_data['bl_pct_up'] : $thold_data['bl_pct_down']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ($ra ? ST_NOTIFYRA : ST_NOTIFYAL),
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
} else {
|
|
$subject = 'Thold Baseline Cache Log';
|
|
|
|
thold_log([
|
|
'type' => 1,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($breach_up ? $thold_data['bl_pct_up'] : $thold_data['bl_pct_down']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_TRIGGERA,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = 0,
|
|
thold_fail_count = 0,
|
|
bl_alert = ?,
|
|
bl_fail_count = ?,
|
|
thold_low = ?,
|
|
thold_hi = ?,
|
|
bl_thold_valid = ?
|
|
WHERE id = ?',
|
|
[
|
|
$thold_data['bl_alert'],
|
|
$thold_data['bl_fail_count'],
|
|
$thold_data['thold_low'],
|
|
$thold_data['thold_hi'],
|
|
$thold_data['bl_thold_valid'],
|
|
$thold_data['id']
|
|
]
|
|
);
|
|
|
|
break;
|
|
case 2: // time based
|
|
if (is_numeric($thold_data['lastread'])) {
|
|
$breach_up = ($thold_data['time_hi'] != '' && $thold_data['lastread'] > $thold_data['time_hi']);
|
|
$breach_down = ($thold_data['time_low'] != '' && $thold_data['lastread'] < $thold_data['time_low']);
|
|
$warning_breach_up = ($thold_data['time_warning_hi'] != '' && $thold_data['lastread'] > $thold_data['time_warning_hi']);
|
|
$warning_breach_down = ($thold_data['time_warning_low'] != '' && $thold_data['lastread'] < $thold_data['time_warning_low']);
|
|
} else {
|
|
$breach_up = $breach_down = $warning_breach_up = $warning_breach_down = false;
|
|
}
|
|
|
|
$step = db_fetch_cell_prepared('SELECT rrd_step
|
|
FROM data_template_data
|
|
WHERE local_data_id = ?',
|
|
[$thold_data['local_data_id']]);
|
|
|
|
// alerts
|
|
$trigger = $thold_data['time_fail_trigger'];
|
|
$time = time() - ($thold_data['time_fail_length'] * $step);
|
|
|
|
$failures = db_fetch_cell_prepared('SELECT COUNT(id)
|
|
FROM plugin_thold_log
|
|
WHERE threshold_id = ?
|
|
AND status IN (?, ?, ?)
|
|
AND time > ?',
|
|
[
|
|
$thold_data['id'],
|
|
ST_TRIGGERA,
|
|
ST_NOTIFYRA,
|
|
ST_NOTIFYAL,
|
|
$time
|
|
]
|
|
);
|
|
|
|
// warnings
|
|
$warning_trigger = $thold_data['time_warning_fail_trigger'];
|
|
$warning_time = time() - ($thold_data['time_warning_fail_length'] * $step);
|
|
|
|
$warning_failures = db_fetch_cell_prepared('SELECT COUNT(id)
|
|
FROM plugin_thold_log
|
|
WHERE threshold_id = ?
|
|
AND status IN (?, ?, ?)
|
|
AND time > ?',
|
|
[
|
|
$thold_data['id'],
|
|
ST_NOTIFYWA,
|
|
ST_TRIGGERW,
|
|
ST_NOTIFYRAW,
|
|
$warning_time
|
|
]
|
|
) + $failures;
|
|
|
|
if ($breach_up || $breach_down) {
|
|
$notify = false;
|
|
|
|
thold_debug('Threshold Time Based check breached HI:' . $thold_data['time_hi'] . ' LOW:' . $thold_data['time_low'] . ' VALUE:' . $thold_data['lastread']);
|
|
|
|
$thold_data['thold_alert'] = ($breach_up ? STAT_HI : STAT_LO);
|
|
$thold_data['thold_fail_count'] = $failures;
|
|
|
|
/**
|
|
* we should only re-alert X minutes after last email, not every 5 pollings, etc...
|
|
* re-alert?
|
|
*/
|
|
$realerttime = ($thold_data['repeat_alert'] - 1) * $step;
|
|
$lastemailtime = db_fetch_cell_prepared('SELECT time
|
|
FROM plugin_thold_log
|
|
WHERE threshold_id = ?
|
|
AND status IN (?, ?)
|
|
ORDER BY time DESC
|
|
LIMIT 1',
|
|
[$thold_data['id'], ST_NOTIFYRA, ST_NOTIFYAL]);
|
|
|
|
$ra = ($failures > $trigger && $thold_data['repeat_alert'] && !empty($lastemailtime) && ($lastemailtime + $realerttime <= time()));
|
|
|
|
if (!$maint_dev) {
|
|
$failures++;
|
|
}
|
|
|
|
thold_debug("Alert Time:'$time', Alert Trigger:'$trigger', Alert Failures:'$failures', RealertTime:'$realerttime', LastTime:'$lastemailtime', RA:'$ra', Diff:'" . ($realerttime + $lastemailtime) . "'<'" . time() . "'");
|
|
|
|
if (($failures == $trigger || $ra) && !$maint_dev) {
|
|
$notify = true;
|
|
}
|
|
|
|
if ($notify && !$ra) {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET lastchanged = NOW()
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
|
|
if ($thold_data['persist_ack'] == 'on' || $thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = "on"
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
}
|
|
|
|
// If this is a realert and the operator has reset the ack, don't notify
|
|
if ($notify && $ra && $thold_data['reset_ack'] == 'on' && $thold_data['acknowledgment'] == '') {
|
|
$suspend_notify = true;
|
|
} else {
|
|
$suspend_notify = false;
|
|
}
|
|
|
|
if ($notify) {
|
|
$trigger = false;
|
|
} else {
|
|
$trigger = true;
|
|
}
|
|
|
|
$subject = get_email_subject('ALERT', $trigger, $lastread, $ra, $breach_up, $thold_data);
|
|
|
|
if ($notify) {
|
|
if (!$suspend_notify && !$maint_dev) {
|
|
thold_debug('Alerting is necessary');
|
|
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_alert'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($alert_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_alert_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($alert_emails, $alert_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
if ($notify_different) {
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
}
|
|
|
|
thold_command_execution($thold_data, $h, $breach_up, $breach_down, false);
|
|
|
|
$save = [
|
|
'class' => 'alert',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'repeat_alert' => $ra,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 3;
|
|
$thold_snmp_data['eventSeverity'] = $thold_data['snmp_event_severity'];
|
|
$thold_snmp_data['eventStatus'] = $thold_data['thold_alert'] + 1;
|
|
$thold_snmp_data['eventRealertStatus'] = ($ra ? ($breach_up ? 3 : 2) : 1);
|
|
$thold_snmp_data['eventNotificationType'] = ($ra ? ST_NOTIFYRA : ST_NOTIFYAL) + 1;
|
|
$thold_snmp_data['eventFailCount'] = $failures;
|
|
$thold_snmp_data['eventFailCountTrigger'] = $trigger;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
$thold_snmp_data['eventDescription'] = str_replace('<FAIL_COUNT>', $thold_snmp_data['eventFailCount'], $thold_snmp_data['eventDescription']);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 2,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($breach_up ? $thold_data['time_hi'] : $thold_data['time_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ($ra ? ST_NOTIFYRA : ST_NOTIFYAL),
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
} else {
|
|
thold_log([
|
|
'type' => 2,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($breach_up ? $thold_data['time_hi'] : $thold_data['time_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_TRIGGERA,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
}
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = ?,
|
|
thold_fail_count = ?
|
|
WHERE id = ?',
|
|
[$thold_data['thold_alert'], $failures, $thold_data['id']]);
|
|
} elseif ($warning_breach_up || $warning_breach_down) {
|
|
$notify = false;
|
|
|
|
$thold_data['thold_alert'] = ($warning_breach_up ? STAT_HI : STAT_LO);
|
|
$thold_data['thold_warning_fail_count'] = $warning_failures;
|
|
|
|
/**
|
|
* we should only re-alert X minutes after last email, not every 5 pollings, etc...
|
|
* re-alert?
|
|
*/
|
|
$realerttime = ($thold_data['time_warning_fail_length'] - 1) * $step;
|
|
$lastemailtime = db_fetch_cell_prepared('SELECT time
|
|
FROM plugin_thold_log
|
|
WHERE threshold_id = ?
|
|
AND status IN (?, ?)
|
|
ORDER BY time DESC
|
|
LIMIT 1',
|
|
[$thold_data['id'], ST_NOTIFYRAW, ST_NOTIFYWA]);
|
|
|
|
$ra = ($warning_failures > $warning_trigger && $thold_data['time_warning_fail_length'] && !empty($lastemailtime) && ($lastemailtime + $realerttime <= time()));
|
|
|
|
if (!$maint_dev) {
|
|
$warning_failures++;
|
|
}
|
|
|
|
thold_debug("Warn Time:'$warning_time', Warn Trigger:'$warning_trigger', Warn Failures:'$warning_failures', RealertTime:'$realerttime', LastTime:'$lastemailtime', RA:'$ra', Diff:'" . ($realerttime + $lastemailtime) . "'<'" . time() . "'");
|
|
|
|
if (($warning_failures == $warning_trigger || $ra) && !$maint_dev) {
|
|
$notify = true;
|
|
}
|
|
|
|
if ($notify && !$ra) {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET lastchanged = NOW()
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
|
|
if ($thold_data['persist_ack'] == 'on' || $thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = "on"
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
}
|
|
|
|
// If this is a realert and the operator has reset the ack, don't notify
|
|
if ($notify && $ra && $thold_data['reset_ack'] == 'on' && $thold_data['acknowledgment'] == '') {
|
|
$suspend_notify = true;
|
|
} else {
|
|
$suspend_notify = false;
|
|
}
|
|
|
|
if ($notify) {
|
|
$trigger = false;
|
|
} else {
|
|
$trigger = true;
|
|
}
|
|
|
|
$ra = ($warning_failures > $warning_trigger) ? true : false;
|
|
|
|
$subject = get_email_subject('WARNING', $trigger, $lastread, $ra, $warning_breach_up, $thold_data);
|
|
|
|
if ($notify) {
|
|
if (!$suspend_notify && !$maint_dev) {
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
$message = get_thold_warning_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
$save = [
|
|
'class' => 'warn',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'repeat_alert' => $ra,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_warning_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 2;
|
|
$thold_snmp_data['eventSeverity'] = $thold_data['snmp_event_warning_severity'];
|
|
$thold_snmp_data['eventStatus'] = $thold_data['thold_alert'] + 1;
|
|
$thold_snmp_data['eventRealertStatus'] = ($ra ? ($warning_breach_up ? 3 : 2) : 1);
|
|
$thold_snmp_data['eventNotificationType'] = ($ra ? ST_NOTIFYRAW : ST_NOTIFYWA) + 1;
|
|
$thold_snmp_data['eventFailCount'] = $warning_failures;
|
|
$thold_snmp_data['eventFailCountTrigger'] = $warning_trigger;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
$thold_snmp_data['eventDescription'] = str_replace('<FAIL_COUNT>', $thold_snmp_data['eventFailCount'], $thold_snmp_data['eventDescription']);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 2,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($breach_up ? $thold_data['time_hi'] : $thold_data['time_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ($ra ? ST_NOTIFYRAW : ST_NOTIFYWA),
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
} elseif ($alertstat != 0 && $warning_failures < $warning_trigger && $failures < $trigger) {
|
|
$subject = get_email_subject('ALERT > WARNING', false, $lastread, false, $warning_breach_up, $thold_data);
|
|
|
|
thold_log([
|
|
'type' => 2,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($warning_breach_up ? $thold_data['time_hi'] : $thold_data['time_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_NOTIFYRAW,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
} else {
|
|
thold_log([
|
|
'type' => 2,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => ($warning_breach_up ? $thold_data['time_hi'] : $thold_data['time_low']),
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_TRIGGERW,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $warning_emails,
|
|
'bcc_emails' => $warning_bcc_emails]
|
|
);
|
|
}
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = ?,
|
|
thold_warning_fail_count = ?,
|
|
thold_fail_count = ?
|
|
WHERE id = ?',
|
|
[$thold_data['thold_alert'], $warning_failures, $failures, $thold_data['id']]);
|
|
} else {
|
|
thold_debug('Threshold Time Based check is Normal HI:' . $thold_data['time_hi'] . ' LOW:' . $thold_data['time_low'] . ' VALUE:' . $thold_data['lastread']);
|
|
|
|
$subject = get_email_subject('NORMAL', false, $lastread, false, false, $thold_data);
|
|
|
|
if ($alertstat != 0 && $warning_failures < $warning_trigger && $thold_data['restored_alert'] != 'on') {
|
|
if (!$maint_dev) {
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['restored_alert'] != 'on') {
|
|
$message = get_thold_restoral_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
$save = [
|
|
'class' => 'warn2normal',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_normal_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 1;
|
|
$thold_snmp_data['eventSeverity'] = 1;
|
|
$thold_snmp_data['eventStatus'] = 1;
|
|
$thold_snmp_data['eventNotificationType'] = ST_NOTIFYRS + 1;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 2,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => '',
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_NOTIFYRS,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $warning_emails,
|
|
'bcc_emails' => $warning_bcc_emails]
|
|
);
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = 0,
|
|
lastchanged = NOW(),
|
|
thold_warning_fail_count = ?,
|
|
thold_fail_count = ?
|
|
WHERE id = ?',
|
|
[$warning_failures, $failures, $thold_data['id']]);
|
|
|
|
if ($thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = ""
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
} elseif ($alertstat != 0 && $failures < $trigger && $thold_data['restored_alert'] != 'on') {
|
|
$subject = get_email_subject('NORMAL', false, $lastread, false, false, $thold_data);
|
|
|
|
if (!$maint_dev) {
|
|
if ($syslog) {
|
|
logger($subject, $url, $syslog_priority, $syslog_facility);
|
|
}
|
|
|
|
$notify_list_id = $thold_data['notify_alert'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($alert_emails) != '' && $thold_data['restored_alert'] != 'on') {
|
|
$message = get_thold_restoral_text($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id']);
|
|
|
|
thold_mail($alert_emails, $alert_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file, $thold_data['graph_timespan']);
|
|
}
|
|
|
|
if ($notify_different) {
|
|
$notify_list_id = $thold_data['notify_warning'];
|
|
$format_file = thold_get_thold_notification_format_file($thold_data['id'], $notify_list_id);
|
|
|
|
if (trim($warning_emails) != '' && $thold_data['acknowledgment'] == '') {
|
|
thold_mail($warning_emails, $warning_bcc_emails, '', $subject, $message, $file_array, '', $notify_list_id, $h, $format_file);
|
|
}
|
|
}
|
|
|
|
thold_command_execution($thold_data, $h, false, false, true);
|
|
|
|
$save = [
|
|
'class' => 'alert2normal',
|
|
'thold_data' => $thold_data,
|
|
'subject' => $subject,
|
|
'host_data' => $h,
|
|
'breach_up' => $breach_up,
|
|
'breach_down' => $breach_down,
|
|
'warning_breach_up' => $warning_breach_up,
|
|
'warning_breach_down' => $warning_breach_down
|
|
];
|
|
|
|
api_plugin_hook_function('thold_action', $save);
|
|
|
|
if ($thold_snmp_traps && $thold_snmp_normal_traps) {
|
|
$thold_snmp_data = get_thold_snmp_data($thold_data['data_source_name'], $thold_data, $h, $thold_data['lastread']);
|
|
|
|
$thold_snmp_data['eventClass'] = 1;
|
|
$thold_snmp_data['eventSeverity'] = 1;
|
|
$thold_snmp_data['eventStatus'] = 1;
|
|
$thold_snmp_data['eventNotificationType'] = ST_NOTIFYRS + 1;
|
|
$thold_snmp_data['eventDeviceIp'] = gethostbyname($h['hostname']);
|
|
|
|
thold_snmptrap($thold_snmp_data, SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite);
|
|
}
|
|
}
|
|
|
|
thold_log([
|
|
'type' => 2,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_data['id'],
|
|
'threshold_value' => '',
|
|
'current' => $thold_data['lastread'],
|
|
'status' => ST_NOTIFYRS,
|
|
'description' => ($maint_dev ? $subject . '. ' . __('Only logging, maint device', 'thold') : $subject),
|
|
'emails' => $alert_emails,
|
|
'bcc_emails' => $alert_bcc_emails]
|
|
);
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_alert = 0,
|
|
lastchanged = NOW(),
|
|
thold_warning_fail_count = ?,
|
|
thold_fail_count = ?
|
|
WHERE id = ?',
|
|
[$warning_failures, $failures, $thold_data['id']]);
|
|
|
|
if ($thold_data['reset_ack'] == 'on') {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment=""
|
|
WHERE id = ?',
|
|
[$thold_data['id']]);
|
|
}
|
|
} else {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_fail_count = ?,
|
|
thold_warning_fail_count = ?
|
|
WHERE id = ?',
|
|
[$failures, $warning_failures, $thold_data['id']]);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
function get_email_subject($phase, $trigger, $lastread, $ra, $breach_up, &$thold_data) {
|
|
$peralert = read_config_option('thold_enable_per_thold_body');
|
|
|
|
// setup base units
|
|
$baseu = db_fetch_cell_prepared('SELECT base_value
|
|
FROM graph_templates_graph
|
|
WHERE local_graph_id = ?',
|
|
[$thold_data['local_graph_id']]);
|
|
|
|
if ($thold_data['data_type'] == 2) {
|
|
$suffix = false;
|
|
} else {
|
|
$suffix = true;
|
|
}
|
|
|
|
$show_datasource = thold_datasource_required(thold_get_cached_name($thold_data), $thold_data['data_source_name']);
|
|
$show_units = ($thold_data['show_units'] ? true : false);
|
|
$units_suffix = $thold_data['units_suffix'];
|
|
$decimals = $thold_data['decimals'] >= 0 ? $thold_data['decimals'] : 2;
|
|
|
|
$hostname = db_fetch_cell_prepared('SELECT hostname
|
|
FROM host
|
|
WHERE id = ?',
|
|
[$thold_data['host_id']]);
|
|
|
|
$site = db_fetch_cell_prepared('SELECT s.name
|
|
FROM sites AS s
|
|
JOIN host AS h ON h.site_id = s.id
|
|
WHERE h.id = ?',
|
|
[$thold_data['host_id']]);
|
|
|
|
if (!$site) {
|
|
$site = __('Default', 'thold');
|
|
}
|
|
|
|
switch($thold_data['thold_type']) {
|
|
case '0': // High Low
|
|
if ($phase == 'ALERT') {
|
|
if ($breach_up) {
|
|
$value = $thold_data['thold_hi'];
|
|
} else {
|
|
$value = $thold_data['thold_low'];
|
|
}
|
|
} elseif ($phase == 'WARNING') {
|
|
if ($breach_up) {
|
|
$value = $thold_data['thold_warning_hi'];
|
|
} else {
|
|
$value = $thold_data['thold_warning_low'];
|
|
}
|
|
} elseif ($phase == 'ALERT > WARNING') {
|
|
if ($breach_up) {
|
|
$value = $thold_data['thold_warning_hi'];
|
|
} else {
|
|
$value = $thold_data['thold_warning_low'];
|
|
}
|
|
}
|
|
|
|
break;
|
|
case '1': // Baseline
|
|
if ($breach_up) {
|
|
$value = $thold_data['thold_hi'];
|
|
} else {
|
|
$value = $thold_data['thold_low'];
|
|
}
|
|
|
|
break;
|
|
case '2': // Time Based
|
|
if ($phase == 'ALERT') {
|
|
if ($breach_up) {
|
|
$value = $thold_data['time_hi'];
|
|
} else {
|
|
$value = $thold_data['time_low'];
|
|
}
|
|
} elseif ($phase == 'WARNING') {
|
|
if ($breach_up) {
|
|
$value = $thold_data['time_warning_hi'];
|
|
} else {
|
|
$value = $thold_data['time_warning_low'];
|
|
}
|
|
} elseif ($phase == 'ALERT > WARNING') {
|
|
if ($breach_up) {
|
|
$value = $thold_data['time_warning_hi'];
|
|
} else {
|
|
$value = $thold_data['time_warning_low'];
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (!isset($value)) {
|
|
$value = $thold_data['lastread'];
|
|
}
|
|
|
|
if ($phase == 'NORMAL') {
|
|
if ($thold_data['email_subject_restoral'] == '' || $peralert == '') {
|
|
return 'NORMAL: ' . thold_get_cached_name($thold_data) .
|
|
($show_datasource ? ' [' . $thold_data['data_source_name'] . ']' : '') .
|
|
' restored to Normal Threshold with value ' .
|
|
thold_format_number($thold_data['lastread'], $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
} else {
|
|
$find = [
|
|
'<PHASE>',
|
|
'<THOLDVALUE>',
|
|
'<CURRENTVALUE>',
|
|
'<THRESHOLDNAME>',
|
|
'<DSNAME>',
|
|
'<HOSTNAME>',
|
|
'<BREACHUP>',
|
|
'<REALERT>',
|
|
'<LOCATION>',
|
|
'<SITE>'
|
|
];
|
|
|
|
$replace = [
|
|
$phase,
|
|
$value,
|
|
$lastread,
|
|
thold_get_cached_name($thold_data),
|
|
$thold_data['data_source_name'],
|
|
$hostname,
|
|
($breach_up ? 'above' : 'below'),
|
|
($ra ? 'is still' : 'went'),
|
|
$thold_data['location'],
|
|
$site
|
|
];
|
|
|
|
return str_replace($find, $replace, $thold_data['email_subject_restoral']);
|
|
}
|
|
} elseif ($phase == 'WARNING' || $phase == 'ALERT > WARNING') {
|
|
if ($trigger) {
|
|
$phase = 'TRIGGER';
|
|
}
|
|
|
|
if ($thold_data['email_subject_warn'] == '' || $peralert == '') {
|
|
if ($phase == 'ALERT > WARNING') {
|
|
return $phase . ': ' . thold_get_cached_name($thold_data) .
|
|
($show_datasource ? ' [' . $thold_data['data_source_name'] . ']' : '') .
|
|
' changed to Warning Threshold with value ' .
|
|
thold_format_number($thold_data['lastread'], $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
} else {
|
|
return $phase . ': ' . thold_get_cached_name($thold_data) .
|
|
($show_datasource ? ' [' . $thold_data['data_source_name'] . ']' : '') . ' ' .
|
|
($ra ? 'is still' : 'went') . ' ' .
|
|
($breach_up ? 'above' : 'below') .
|
|
($thold_data['thold_type'] == 1 ? ' Baseline Threshold of ' : ' Threshold of ') .
|
|
($breach_up ? thold_format_number($value, $decimals, $baseu, $suffix, $show_units, $units_suffix) :
|
|
thold_format_number($value, $decimals, $baseu, $suffix, $show_units, $units_suffix)) . ' with ' .
|
|
thold_format_number($lastread, $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
}
|
|
} else {
|
|
$find = [
|
|
'<PHASE>',
|
|
'<THRESHOLDVALUE>',
|
|
'<CURRENTVALUE>',
|
|
'<THRESHOLDNAME>',
|
|
'<DSNAME>',
|
|
'<HOSTNAME>',
|
|
'<BREACHUP>',
|
|
'<REALERT>',
|
|
'<LOCATION>',
|
|
'<SITE>'
|
|
];
|
|
|
|
$replace = [
|
|
$phase,
|
|
$value,
|
|
$lastread,
|
|
thold_get_cached_name($thold_data),
|
|
$thold_data['data_source_name'],
|
|
$hostname,
|
|
($breach_up ? 'above' : 'below'),
|
|
($ra ? 'is still' : 'went'),
|
|
$thold_data['location'],
|
|
$site
|
|
];
|
|
|
|
return str_replace($find, $replace, $thold_data['email_subject_warn']);
|
|
}
|
|
} else {
|
|
if ($trigger) {
|
|
$phase = 'TRIGGER';
|
|
}
|
|
|
|
if ($thold_data['email_subject'] == '' || $peralert == '') {
|
|
return $phase . ': ' . thold_get_cached_name($thold_data) .
|
|
($show_datasource ? ' [' . $thold_data['data_source_name'] . ']' : '') . ' ' .
|
|
($ra ? 'is still' : 'went') . ' ' .
|
|
($breach_up ? 'above' : 'below') .
|
|
($thold_data['thold_type'] == 1 ? ' Baseline Threshold of ' : ' Threshold of ') .
|
|
($breach_up ? thold_format_number($value, $decimals, $baseu, $suffix, $show_units, $units_suffix) :
|
|
thold_format_number($value, $decimals, $baseu, $suffix, $show_units, $units_suffix)) . ' with ' .
|
|
thold_format_number($lastread, $decimals, $baseu, $suffix, $show_units, $units_suffix);
|
|
} else {
|
|
$find = [
|
|
'<PHASE>',
|
|
'<THRESHOLDVALUE>',
|
|
'<CURRENTVALUE>',
|
|
'<THRESHOLDNAME>',
|
|
'<DSNAME>',
|
|
'<HOSTNAME>',
|
|
'<BREACHUP>',
|
|
'<REALERT>',
|
|
'<LOCATION>',
|
|
'<SITE>'
|
|
];
|
|
|
|
$replace = [
|
|
$phase,
|
|
$value,
|
|
$lastread,
|
|
thold_get_cached_name($thold_data),
|
|
$thold_data['data_source_name'],
|
|
$hostname,
|
|
($breach_up ? 'above' : 'below'),
|
|
($ra ? 'is still' : 'went'),
|
|
$thold_data['location'],
|
|
$site
|
|
];
|
|
|
|
return str_replace($find, $replace, $thold_data['email_subject']);
|
|
}
|
|
}
|
|
}
|
|
|
|
function get_thold_snmp_data($data_source_name, $thold, $h, $currentval) {
|
|
global $thold_types;
|
|
|
|
// Do some replacement of variables
|
|
$thold_snmp_data = [
|
|
'eventDateRFC822' => date(DATE_RFC822),
|
|
'eventClass' => 3, // default - see CACTI-THOLD-MIB
|
|
'eventSeverity' => 3, // default - see CACTI-THOLD-MIB
|
|
'eventCategory' => ($thold['snmp_event_category'] ? $thold['snmp_event_category'] : ''),
|
|
'eventSource' => $thold['name_cache'],
|
|
'eventDescription' => '', // default - see CACTI-THOLD-MIB
|
|
'eventDevice' => $h['hostname'],
|
|
'eventDataSource' => $data_source_name,
|
|
'eventCurrentValue' => $currentval,
|
|
'eventHigh' => ($thold['thold_type'] == 0 ? $thold['thold_hi'] : ($thold['thold_type'] == 2 ? $thold['time_warning_hi'] : '')),
|
|
'eventLow' => ($thold['thold_type'] == 0 ? $thold['thold_low'] : ($thold['thold_type'] == 2 ? $thold['time_warning_low'] : '')),
|
|
'eventNotificationType' => 5, // default - see CACTI-THOLD-MIB
|
|
'eventStatus' => 3, // default - see CACTI-THOLD-MIB
|
|
'eventRealertStatus' => 1, // default - see CACTI-THOLD-MIB
|
|
'eventFailDuration' => 0, // default - see CACTI-THOLD-MIB
|
|
'eventFailCount' => 0, // default - see CACTI-THOLD-MIB
|
|
'eventFailDurationTrigger' => 0, // default - see CACTI-THOLD-MIB
|
|
'eventFailCountTrigger' => 0, // default - see CACTI-THOLD-MIB
|
|
];
|
|
|
|
if (isset($thold_types[$thold['thold_type']])) {
|
|
$thold_snmp_data['eventThresholdType'] = $thold['thold_type'];
|
|
} else {
|
|
$thold_snmp_data['eventThresholdType'] = 1;
|
|
}
|
|
|
|
// substitute snmp query data
|
|
$snmp_event_description = thold_expand_string($thold, $thold['snmp_event_description']);
|
|
|
|
$snmp_event_description = thold_str_replace('<THRESHOLDNAME>', $thold_snmp_data['eventSource'], $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<HOSTNAME>', $thold_snmp_data['eventDevice'], $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<TEMPLATE_ID>', ($thold['thold_template_id'] ? $thold['thold_template_id'] : 'none'), $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<TEMPLATE_NAME>', (isset($thold['name_cache']) ? $thold['name_cache'] : 'none'), $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<THR_TYPE>', $thold_snmp_data['eventThresholdType'], $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<DS_NAME>', $thold_snmp_data['eventDataSource'], $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<HI>', $thold_snmp_data['eventHigh'], $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<LOW>', $thold_snmp_data['eventLow'], $snmp_event_description);
|
|
$snmp_event_description = thold_str_replace('<EVENT_CATEGORY>', $thold_snmp_data['eventCategory'], $snmp_event_description);
|
|
$thold_snmp_data['eventDescription'] = $snmp_event_description;
|
|
|
|
return $thold_snmp_data;
|
|
}
|
|
|
|
function thold_expand_string($thold_data, $string) {
|
|
global $config;
|
|
|
|
include_once($config['library_path'] . '/variables.php');
|
|
|
|
$str = $string;
|
|
|
|
// Handle the blank string case
|
|
if ($str == '') {
|
|
if (isset($thold_data['thold_template_id']) && $thold_data['thold_template_id'] > 0) {
|
|
$str = db_fetch_cell_prepared('SELECT suggested_name
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$thold_data['thold_template_id']]);
|
|
|
|
if ($str == '') {
|
|
$str = '|data_source_description| [|data_source_name|]';
|
|
}
|
|
} elseif (isset($thold_data['data_source_name']) && $thold_data['data_source_name'] > 0) {
|
|
$str = thold_get_default_suggested_name(['data_source_name' => $data_source_name], 0);
|
|
}
|
|
}
|
|
|
|
// Do core replacements
|
|
if (cacti_sizeof($thold_data) && isset($thold_data['local_graph_id']) && isset($thold_data['local_data_id'])) {
|
|
$lg = db_fetch_row_prepared('SELECT *
|
|
FROM graph_local
|
|
WHERE id = ?',
|
|
[$thold_data['local_graph_id']]);
|
|
|
|
if (cacti_sizeof($lg)) {
|
|
// Handle speed queries replacements first
|
|
if (strpos($str, '|query_ifHighSpeed|') !== false) {
|
|
$value = thold_substitute_snmp_query_data('|query_ifHighSpeed|', $lg['host_id'], $lg['snmp_query_id'], $lg['snmp_index'], read_config_option('max_data_query_field_length'));
|
|
|
|
// if we are trying to replace 10GE of some odd data
|
|
if (!is_numeric($value) || $value == 0) {
|
|
$value = read_config_option('thold_empty_if_speed_default');
|
|
}
|
|
|
|
$str = str_replace('|query_ifHighSpeed|', $value, $str);
|
|
} elseif (strpos($str, '|query_ifSpeed|') !== false) {
|
|
$value = thold_substitute_snmp_query_data('|query_ifSpeed|', $lg['host_id'], $lg['snmp_query_id'], $lg['snmp_index'], read_config_option('max_data_query_field_length'));
|
|
|
|
if (!is_numeric($value) || $value == 0) {
|
|
$value = read_config_option('thold_empty_if_speed_default');
|
|
}
|
|
|
|
$str = str_replace('|query_ifSpeed|', $value, $str);
|
|
}
|
|
|
|
$str = expand_title($lg['host_id'], $lg['snmp_query_id'], $lg['snmp_index'], $str);
|
|
$str = thold_substitute_custom_data($str, '|', '|', $thold_data['local_data_id']);
|
|
|
|
$data = [
|
|
'str' => $str,
|
|
'thold_data' => $thold_data,
|
|
'local_graph' => $lg
|
|
];
|
|
|
|
$data = api_plugin_hook_function('thold_substitute_custom_data', $data);
|
|
|
|
if (isset($data['str'])) {
|
|
$str = $data['str'];
|
|
}
|
|
|
|
if (strpos($str, '|query_') !== false) {
|
|
cacti_log("WARNING: Expression Replacement for '$str' in THold '" . $thold_data['name'] . "' Failed, A Reindex may be required!");
|
|
}
|
|
}
|
|
|
|
if (strpos($str, '|host_') !== false && !empty($device_id)) {
|
|
$str = thold_substitute_host_data($str, '|', '|', $device_id);
|
|
}
|
|
|
|
// Replace |graph_title|
|
|
if (strpos($str, '|graph_title|') !== false) {
|
|
$title = get_graph_title($thold_data['local_graph_id']);
|
|
$str = str_replace('|graph_title|', $title, $str);
|
|
}
|
|
|
|
// Replace |data_source_description|
|
|
if (strpos($str, '|data_source_description|') !== false) {
|
|
$data_source_desc = db_fetch_cell_prepared('SELECT name_cache
|
|
FROM data_template_data
|
|
WHERE local_data_id = ?',
|
|
[$thold_data['local_data_id']]);
|
|
|
|
$str = str_replace('|data_source_description|', $data_source_desc, $str);
|
|
}
|
|
|
|
// Replace |data_source_name|
|
|
if (strpos($str, '|data_source_name|') !== false) {
|
|
$str = str_replace('|data_source_name|', $thold_data['data_source_name'], $str);
|
|
}
|
|
}
|
|
|
|
return trim($str);
|
|
}
|
|
|
|
function thold_command_execution(&$thold_data, &$h, $breach_up, $breach_down, $breach_norm = false) {
|
|
if (read_config_option('thold_enable_scripts') == 'on') {
|
|
$output = [];
|
|
$return = 0;
|
|
$command_executed = false;
|
|
$data_source_name = $thold_data['data_source_name'];
|
|
$queue = read_config_option('thold_notification_queue');
|
|
|
|
if ($breach_up && $thold_data['trigger_cmd_high'] != '') {
|
|
$cmd = thold_replace_threshold_tags($thold_data['trigger_cmd_high'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name);
|
|
|
|
$cmd = thold_expand_string($thold_data, $cmd);
|
|
|
|
$environment = thold_set_environ($thold_data['trigger_cmd_high'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name);
|
|
|
|
if ($queue == 'on') {
|
|
$data = [
|
|
'command' => $cmd,
|
|
'data' => $thold_data,
|
|
'environment' => $environment
|
|
];
|
|
|
|
thold_notification_add('thold_cmd', $data, 'id', 0, $h);
|
|
} else {
|
|
exec($cmd, $output, $return);
|
|
}
|
|
|
|
$command_executed = true;
|
|
} elseif ($breach_down && $thold_data['trigger_cmd_low'] != '') {
|
|
$cmd = thold_replace_threshold_tags($thold_data['trigger_cmd_low'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name);
|
|
$cmd = thold_expand_string($thold_data, $cmd);
|
|
|
|
$environment = thold_set_environ($thold_data['trigger_cmd_high'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name);
|
|
|
|
if ($queue == 'on') {
|
|
$data = [
|
|
'command' => $cmd,
|
|
'data' => $thold_data,
|
|
'environment' => $environment
|
|
];
|
|
|
|
thold_notification_add('thold_cmd', $data, 'id', 0, $h);
|
|
} else {
|
|
exec($cmd, $output, $return);
|
|
}
|
|
|
|
$command_executed = true;
|
|
} elseif ($breach_norm && $thold_data['trigger_cmd_norm'] != '') {
|
|
$cmd = thold_replace_threshold_tags($thold_data['trigger_cmd_norm'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name);
|
|
$cmd = thold_expand_string($thold_data, $cmd);
|
|
|
|
$environment = thold_set_environ($thold_data['trigger_cmd_high'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name);
|
|
|
|
if ($queue == 'on') {
|
|
$data = [
|
|
'command' => $cmd,
|
|
'data' => $thold_data,
|
|
'environment' => $environment
|
|
];
|
|
|
|
thold_notification_add('thold_cmd', $data, 'id', 0, $h);
|
|
} else {
|
|
exec($cmd, $output, $return);
|
|
}
|
|
|
|
$command_executed = true;
|
|
}
|
|
|
|
if ($queue == '' && $command_executed) {
|
|
thold_process_command_output($output, $return, 'thold', $thold_data, $cmd);
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_process_command_output(&$output, $return, $topic = 'thold_cmd', &$data = [], $command = '') {
|
|
if ($topic == 'thold_cmd') {
|
|
if (cacti_sizeof($output)) {
|
|
if ($return > 0) {
|
|
cacti_log('WARNING: Threshold command execution for TH[' . $data['id'] . '] returned ' . $return . ', with output ' . implode(', ', $output), false, 'THOLD');
|
|
} else {
|
|
cacti_log('NOTE: Threshold command execution for TH[' . $data['id'] . '] returned ' . $return . ', with output ' . implode(', ', $output), false, 'THOLD');
|
|
}
|
|
} else {
|
|
if ($return > 0) {
|
|
cacti_log('WARNING: Threshold command execution for TH[' . $data['id'] . '] returned ' . $return . ', with no output.', false, 'THOLD');
|
|
} else {
|
|
cacti_log('NOTE: Threshold command execution for TH[' . $data['id'] . '] returned ' . $return . ', with no output.', false, 'THOLD');
|
|
}
|
|
}
|
|
} elseif ($topic == 'thold_dhost_cmd') {
|
|
cacti_log('Device Down Command for Device[' . $data['id'] . '] Command[' . $command . '] ExitStatus[' . $return . '] Output[' . implode(' ', $output) . ']', false, 'THOLD');
|
|
} elseif ($topic == 'thold_uhost_cmd') {
|
|
cacti_log('Device Up Command for Device[' . $data['id'] . '] Command[' . $command . '] ExitStatus[' . $return . '] Output[' . implode(' ', $output) . ']', false, 'THOLD');
|
|
}
|
|
}
|
|
|
|
function thold_putenv($name_value_pair, $reset = false) {
|
|
static $env_queue = [];
|
|
|
|
$queue = read_config_option('thold_notification_queue');
|
|
|
|
if ($reset == true) {
|
|
$env_queue = [];
|
|
}
|
|
|
|
if ($queue == 'on') {
|
|
$env_queue[] = $name_value_pair;
|
|
} else {
|
|
putenv($name_value_pair);
|
|
}
|
|
|
|
return $env_queue;
|
|
}
|
|
|
|
function thold_set_environ($text, &$thold, &$h, $currentval, $local_graph_id, $data_source_name) {
|
|
global $thold_types;
|
|
|
|
$httpurl = read_config_option('base_url');
|
|
|
|
$queue = read_config_option('thold_notification_queue');
|
|
|
|
// Do some replacement of variables
|
|
thold_putenv('THOLD_ID=' . $thold['id'], true);
|
|
thold_putenv('THOLD_DATA_ID=' . $thold['local_data_id']);
|
|
thold_putenv('THOLD_GRAPH_ID=' . $thold['local_graph_id']);
|
|
thold_putenv('THOLD_DESCRIPTION=' . $h['description']);
|
|
thold_putenv('THOLD_HOSTNAME=' . $h['hostname']);
|
|
thold_putenv('THOLD_GRAPHID=' . $local_graph_id);
|
|
|
|
thold_putenv('THOLD_CURRENTVALUE=' . $currentval);
|
|
thold_putenv('THOLD_THRESHOLDNAME=' . $thold['name_cache']);
|
|
thold_putenv('THOLD_DSNAME=' . $data_source_name);
|
|
thold_putenv('THOLD_TIMEINSTATE=' . get_timeinstate($h));
|
|
thold_putenv('THOLD_HOST_STATUS=' . $h['status']);
|
|
thold_putenv('THOLD_HOST_FAIL_DATE=' . $h['status_fail_date']);
|
|
thold_putenv('THOLD_HOST_REC_DATE=' . $h['status_rec_date']);
|
|
thold_putenv('THOLD_HOST_LAST_ERROR=' . $h['status_last_error']);
|
|
|
|
if (isset($thold_types[$thold['thold_type']])) {
|
|
thold_putenv('THOLD_THOLDTYPE=' . $thold_types[$thold['thold_type']]);
|
|
} else {
|
|
thold_putenv('THOLD_THOLDTYPE=');
|
|
}
|
|
|
|
if ($thold['notes'] != '') {
|
|
$notes = thold_replace_threshold_tags($thold['notes'], $thold, $h, $currentval, $local_graph_id, $data_source_name);
|
|
thold_putenv('THOLD_NOTES=' . $notes);
|
|
} else {
|
|
thold_putenv('THOLD_NOTES=' . '');
|
|
}
|
|
|
|
if ($thold['external_id'] != '') {
|
|
thold_putenv('THOLD_EXTERNAL_ID=' . $thold['external_id']);
|
|
}
|
|
|
|
thold_putenv('THOLD_DEVICENOTE=' . $thold['dnotes']);
|
|
|
|
if ($thold['thold_type'] == 0) {
|
|
thold_putenv('THOLD_HI=' . $thold['thold_hi']);
|
|
thold_putenv('THOLD_LOW=' . $thold['thold_low']);
|
|
thold_putenv('THOLD_TRIGGER=' . $thold['thold_fail_trigger']);
|
|
thold_putenv('THOLD_DURATION=' . '');
|
|
} elseif ($thold['thold_type'] == 2) {
|
|
thold_putenv('THOLD_HI=' . $thold['time_hi']);
|
|
thold_putenv('THOLD_LOW=' . $thold['time_low']);
|
|
thold_putenv('THOLD_TRIGGER=' . $thold['time_fail_trigger']);
|
|
thold_putenv('THOLD_DURATION=' . plugin_thold_duration_convert($thold['local_data_id'], $thold['time_fail_length'], 'time'));
|
|
} else {
|
|
thold_putenv('THOLD_HI=' . '');
|
|
thold_putenv('THOLD_LOW=' . '');
|
|
thold_putenv('THOLD_TRIGGER=' . '');
|
|
thold_putenv('THOLD_DURATION=' . '');
|
|
}
|
|
|
|
thold_putenv('THOLD_TIME=' . time());
|
|
thold_putenv('THOLD_DATE=' . date(CACTI_DATE_TIME_FORMAT));
|
|
thold_putenv('THOLD_DATE_RFC822=' . date(DATE_RFC822));
|
|
|
|
$environment = thold_putenv('THOLD_URL=' . html_escape("$httpurl/graph.php?local_graph_id=$local_graph_id"));
|
|
|
|
return $environment;
|
|
}
|
|
|
|
function thold_replace_threshold_tags($text, &$thold, &$h, $currentval, $local_graph_id, $data_source_name) {
|
|
global $thold_types;
|
|
|
|
if (substr(read_config_option('base_url'), 0, 4) != 'http') {
|
|
if (read_config_option('force_https') == 'on') {
|
|
$prefix = 'https://';
|
|
} else {
|
|
$prefix = 'http://';
|
|
}
|
|
|
|
set_config_option('base_url', $prefix . read_config_option('base_url'));
|
|
}
|
|
|
|
$httpurl = read_config_option('base_url', true);
|
|
|
|
$site = db_fetch_cell_prepared('SELECT name
|
|
FROM sites
|
|
WHERE id = ?',
|
|
[$h['site_id']]);
|
|
|
|
if (!$site) {
|
|
$site = __('Default', 'thold');
|
|
}
|
|
|
|
// Do some replacement of variables
|
|
$text = thold_str_replace('<DESCRIPTION>', $h['description'], $text);
|
|
$text = thold_str_replace('<HOSTNAME>', $h['hostname'], $text);
|
|
$text = thold_str_replace('<LOCATION>', $h['location'], $text);
|
|
$text = thold_str_replace('<SITE>', $site, $text);
|
|
$text = thold_str_replace('<GRAPHID>', $local_graph_id, $text);
|
|
$text = thold_str_replace('<THOLD_ID>', $thold['id'], $text);
|
|
|
|
$text = thold_str_replace('<CURRENTVALUE>', $currentval, $text);
|
|
$text = thold_str_replace('<THRESHOLDNAME>', $thold['name_cache'], $text);
|
|
$text = thold_str_replace('<DSNAME>', $data_source_name, $text);
|
|
|
|
if (isset($thold_types[$thold['thold_type']])) {
|
|
$text = thold_str_replace('<THOLDTYPE>', $thold_types[$thold['thold_type']], $text);
|
|
}
|
|
|
|
$text = thold_str_replace('<NOTES>', $thold['notes'], $text);
|
|
$text = thold_str_replace('<DNOTES>', $thold['dnotes'], $text);
|
|
$text = thold_str_replace('<DEVICENOTE>', $thold['dnotes'], $text);
|
|
$text = thold_str_replace('<EXTERNALID>', $thold['external_id'], $text);
|
|
|
|
if ($thold['thold_type'] == 0) {
|
|
$text = thold_str_replace('<HI>', $thold['thold_hi'], $text);
|
|
$text = thold_str_replace('<LOW>', $thold['thold_low'], $text);
|
|
$text = thold_str_replace('<TRIGGER>', $thold['thold_fail_trigger'], $text);
|
|
$text = thold_str_replace('<DURATION>', '', $text);
|
|
} elseif ($thold['thold_type'] == 2) {
|
|
$text = thold_str_replace('<HI>', $thold['time_hi'], $text);
|
|
$text = thold_str_replace('<LOW>', $thold['time_low'], $text);
|
|
$text = thold_str_replace('<TRIGGER>', $thold['time_fail_trigger'], $text);
|
|
$text = thold_str_replace('<DURATION>', plugin_thold_duration_convert($thold['local_data_id'], $thold['time_fail_length'], 'time'), $text);
|
|
} else {
|
|
$text = thold_str_replace('<HI>', '', $text);
|
|
$text = thold_str_replace('<LOW>', '', $text);
|
|
$text = thold_str_replace('<TRIGGER>', '', $text);
|
|
$text = thold_str_replace('<DURATION>', '', $text);
|
|
}
|
|
|
|
$text = thold_str_replace('<TIME>', time(), $text);
|
|
$text = thold_str_replace('<DATE>', date(CACTI_DATE_TIME_FORMAT), $text);
|
|
$text = thold_str_replace('<DATE_RFC822>', date(DATE_RFC822), $text);
|
|
|
|
$text = thold_str_replace('<URL>', "<a href='" . html_escape("$httpurl/graph.php?local_graph_id=$local_graph_id") . "'>" . __('Link to Graph in Cacti', 'thold') . '</a>', $text);
|
|
|
|
$data = [
|
|
'thold_data' => $thold,
|
|
'text' => $text
|
|
];
|
|
|
|
$data = api_plugin_hook_function('thold_replacement_text', $data);
|
|
|
|
if (isset($data['text'])) {
|
|
$text = $data['text'];
|
|
}
|
|
|
|
return $text;
|
|
}
|
|
|
|
function get_thold_alert_text($data_source_name, $thold, $h, $currentval, $local_graph_id) {
|
|
$alert_text = read_config_option('thold_alert_text');
|
|
$httpurl = read_config_option('base_url');
|
|
$peralert = read_config_option('thold_enable_per_thold_body');
|
|
|
|
if ($peralert == 'on') {
|
|
$alert_text = $thold['email_body'];
|
|
}
|
|
|
|
// make sure the alert text has been set
|
|
if ($alert_text == '') {
|
|
$alert_text = __('<html><body>An alert has been issued that requires your attention.<br><br><b>Device</b>: <DESCRIPTION> (<HOSTNAME>)<br><b>URL</b>: <URL><br><b>Message</b>: <SUBJECT><br><br><GRAPH></body></html>', 'thold');
|
|
}
|
|
|
|
if ($thold['notes'] != '') {
|
|
$notes = thold_replace_threshold_tags($thold['notes'], $thold, $h, $currentval, $local_graph_id, $data_source_name);
|
|
$alert_text = thold_str_replace('<NOTES>', $notes, $alert_text);
|
|
}
|
|
|
|
$alert_text = thold_replace_threshold_tags($alert_text, $thold, $h, $currentval, $local_graph_id, $data_source_name);
|
|
|
|
return $alert_text;
|
|
}
|
|
|
|
function get_thold_warning_text($data_source_name, $thold, $h, $currentval, $local_graph_id) {
|
|
$warning_text = read_config_option('thold_warning_text');
|
|
$httpurl = read_config_option('base_url');
|
|
$peralert = read_config_option('thold_enable_per_thold_body');
|
|
|
|
if ($peralert == 'on') {
|
|
$warning_text = $thold['email_body_warn'];
|
|
}
|
|
|
|
// make sure the warning text has been set
|
|
if ($warning_text == '') {
|
|
$warning_text = __('<html><body>A warning has been issued that requires your attention.<br><br><b>Device</b>: <DESCRIPTION> (<HOSTNAME>)<br><b>URL</b>: <URL><br><b>Message</b>: <SUBJECT><br><br><GRAPH></body></html>', 'thold');
|
|
}
|
|
|
|
if ($thold['notes'] != '') {
|
|
$notes = thold_replace_threshold_tags($thold['notes'], $thold, $h, $currentval, $local_graph_id, $data_source_name);
|
|
$warning_text = thold_str_replace('<NOTES>', $notes, $warning_text);
|
|
}
|
|
|
|
$warning_text = thold_replace_threshold_tags($warning_text, $thold, $h, $currentval, $local_graph_id, $data_source_name);
|
|
|
|
return $warning_text;
|
|
}
|
|
|
|
function get_thold_restoral_text($data_source_name, $thold, $h, $currentval, $local_graph_id) {
|
|
$restoral_text = read_config_option('thold_restoral_text');
|
|
$httpurl = read_config_option('base_url');
|
|
$peralert = read_config_option('thold_enable_per_thold_body');
|
|
|
|
if ($peralert == 'on') {
|
|
$restoral_text = $thold['email_body_restoral'];
|
|
}
|
|
|
|
// make sure the alert text has been set
|
|
if ($restoral_text == '') {
|
|
$restoral_text = __('<html><body>A Threshold has returned to normal status. <br><br><strong>Device</strong>: <DESCRIPTION> (<HOSTNAME>)<br><strong>URL</strong>: <URL><br><strong>Message</strong>: <SUBJECT><br><br><GRAPH></body></html>', 'thold');
|
|
}
|
|
|
|
if ($thold['notes'] != '') {
|
|
$notes = thold_replace_threshold_tags($thold['notes'], $thold, $h, $currentval, $local_graph_id, $data_source_name);
|
|
$restoral_text = thold_str_replace('<NOTES>', $notes, $restoral_text);
|
|
}
|
|
|
|
$restoral_text = thold_replace_threshold_tags($restoral_text, $thold, $h, $currentval, $local_graph_id, $data_source_name);
|
|
|
|
return $restoral_text;
|
|
}
|
|
|
|
function thold_modify_values_by_cdef(&$thold_data) {
|
|
$cdef = false;
|
|
|
|
if ($thold_data['data_type'] != 1 || empty($thold_data['cdef'])) {
|
|
// Check is the graph item has a cdef
|
|
$cdef = db_fetch_cell_prepared('SELECT MAX(cdef_id)
|
|
FROM graph_templates_item AS gti
|
|
INNER JOIN data_template_rrd AS dtr
|
|
ON gti.task_item_id = dtr.id
|
|
WHERE local_graph_id = ?
|
|
AND dtr.id = ?
|
|
AND gti.graph_type_id IN (4, 5, 6, 7, 8, 20)
|
|
AND dtr.data_source_name = ?',
|
|
[$thold_data['local_graph_id'], $thold_data['data_template_rrd_id'], $thold_data['data_source_name']]);
|
|
}
|
|
|
|
if ($cdef !== false && $cdef > 0 && $thold_data['data_type'] == 1) {
|
|
$thold_data['lastread'] = thold_build_cdef($cdef, $thold_data['lastread'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
|
|
if ($thold_data['thold_type'] == 0) {
|
|
$thold_data['thold_hi'] = thold_build_cdef($cdef, $thold_data['thold_hi'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$thold_data['thold_low'] = thold_build_cdef($cdef, $thold_data['thold_low'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
|
|
$thold_data['thold_warning_hi'] = thold_build_cdef($cdef, $thold_data['thold_warning_hi'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$thold_data['thold_warning_low'] = thold_build_cdef($cdef, $thold_data['thold_warning_low'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
} elseif ($thold_data['thold_type'] == 2) {
|
|
$thold_data['time_hi'] = thold_build_cdef($cdef, $thold_data['time_hi'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$thold_data['time_low'] = thold_build_cdef($cdef, $thold_data['time_low'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
|
|
$thold_data['time_warning_hi'] = thold_build_cdef($cdef, $thold_data['time_warning_hi'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$thold_data['time_warning_low'] = thold_build_cdef($cdef, $thold_data['time_warning_low'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_get_column_by_cdef(&$thold_data, $column = 'lastread') {
|
|
// Check is the graph item has a cdef
|
|
if (isset($thold_data['local_data_id'])) {
|
|
$cdef = db_fetch_cell_prepared('SELECT MAX(cdef_id)
|
|
FROM graph_templates_item AS gti
|
|
INNER JOIN data_template_rrd AS dtr
|
|
ON gti.task_item_id = dtr.id
|
|
WHERE local_graph_id = ?
|
|
AND dtr.id = ?
|
|
AND dtr.data_source_name = ?',
|
|
[
|
|
$thold_data['local_graph_id'],
|
|
$thold_data['data_template_rrd_id'],
|
|
$thold_data['data_source_name']
|
|
]
|
|
);
|
|
|
|
if ($cdef > 0) {
|
|
return thold_build_cdef($cdef, $thold_data['lastread'], $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
}
|
|
|
|
if (isset($thold_data['lastread'])) {
|
|
return $thold_data['lastread'];
|
|
}
|
|
}
|
|
|
|
return '-';
|
|
}
|
|
|
|
function thold_format_number($value, $digits = 2, $baseu = 1024, $show_suffix = true, $show_units = false, $units_suffix = '') {
|
|
$units = '';
|
|
$suffix = '';
|
|
|
|
if ($baseu == 1024 && $show_suffix) {
|
|
$suffix = 'i';
|
|
}
|
|
|
|
if (!is_numeric($value)) {
|
|
return '-';
|
|
}
|
|
|
|
if (empty($baseu)) {
|
|
$baseu = 1000;
|
|
}
|
|
|
|
if ($value == '0') {
|
|
return '0';
|
|
}
|
|
|
|
if (!$show_units && $units_suffix == '') {
|
|
return number_format_i18n($value, $digits, $baseu);
|
|
}
|
|
|
|
if ($units_suffix != '') {
|
|
$suffix = " $units_suffix";
|
|
}
|
|
|
|
if (abs($value) < 1) {
|
|
$units = ' m';
|
|
$value *= $baseu;
|
|
|
|
if (abs($value) < 1) {
|
|
$units = ' µ';
|
|
$value *= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
|
|
if (abs($value) < 1) {
|
|
$units = ' n';
|
|
$value *= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
|
|
if (abs($value) < 1) {
|
|
$units = ' p';
|
|
$value *= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
} else {
|
|
if (abs($value) >= $baseu) {
|
|
$units = ' K';
|
|
$value /= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
|
|
if (abs($value) >= $baseu) {
|
|
$units = ' M';
|
|
$value /= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
|
|
if (abs($value) >= $baseu) {
|
|
$units = ' G';
|
|
$value /= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
|
|
if (abs($value) >= $baseu) {
|
|
$units = ' T';
|
|
$value /= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
|
|
if (abs($value) >= $baseu) {
|
|
$units = ' P';
|
|
$value /= $baseu;
|
|
} else {
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
}
|
|
|
|
return number_format_i18n($value, $digits, $baseu) . $units . $suffix;
|
|
}
|
|
|
|
function get_reference_types($local_data_id = 0) {
|
|
global $config, $timearray;
|
|
|
|
include($config['base_path'] . '/plugins/thold/includes/arrays.php');
|
|
|
|
$poller_interval = read_config_option('poller_interval');
|
|
|
|
$rra_steps = db_fetch_assoc('SELECT DISTINCT dsp.step * dspr.steps AS frequency
|
|
FROM data_source_profiles AS dsp
|
|
INNER JOIN data_source_profiles_rra AS dspr
|
|
ON dsp.id = dspr.data_source_profile_id
|
|
LEFT JOIN data_template_data AS dtd
|
|
ON dtd.data_source_profile_id=dspr.data_source_profile_id
|
|
WHERE dspr.steps > 1 ' . ($local_data_id > 0 ? "AND dtd.local_data_id = $local_data_id" : '') . '
|
|
ORDER BY frequency');
|
|
|
|
$reference_types = [];
|
|
|
|
if (cacti_sizeof($rra_steps)) {
|
|
foreach ($rra_steps as $rra_step) {
|
|
$seconds = $rra_step['frequency'];
|
|
$setting = round($rra_step['frequency'] / $poller_interval, 0);
|
|
|
|
if (isset($timearray[$setting])) {
|
|
$reference_types[$seconds] = $timearray[$setting];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $reference_types;
|
|
}
|
|
|
|
function logger($subject, $urlbreach, $syslog_priority = '', $syslog_facility = '') {
|
|
if ($syslog_priority == '') {
|
|
$syslog_priority = read_config_option('thold_syslog_priority');
|
|
}
|
|
|
|
if ($syslog_facility == '') {
|
|
$syslog_facility = read_config_option('thold_syslog_facility');
|
|
}
|
|
|
|
if ($syslog_priority > 7 || $syslog_priority < 0 || $syslog_priority == '') {
|
|
$syslog_priority = LOG_WARNING;
|
|
set_config_option('thold_syslog_priority', $syslog_priority);
|
|
}
|
|
|
|
if ($syslog_facility == '') {
|
|
$syslog_facility = LOG_DAEMON;
|
|
set_config_option('thold_syslog_facility', $syslog_facility);
|
|
}
|
|
|
|
openlog('CactiTholdLog', LOG_PID | LOG_PERROR, $syslog_facility);
|
|
|
|
syslog($syslog_priority, $subject . ' - ' . $urlbreach);
|
|
|
|
if (function_exists('closelog')) {
|
|
closelog();
|
|
}
|
|
}
|
|
|
|
function ack_logging($thold_id, $desc = '') {
|
|
$thold_data = db_fetch_row_prepared('SELECT name_cache, host_id, thold_hi, thold_low,
|
|
syslog_enabled, syslog_facility, syslog_priority, lastread, local_graph_id
|
|
FROM thold_data
|
|
WHERE id = ?',
|
|
[$thold_id]);
|
|
|
|
if ($thold_data['syslog_enabled']) {
|
|
openlog('CactiTholdLog', LOG_PID | LOG_PERROR, $thold_data['syslog_facility']);
|
|
|
|
syslog($thold_data['syslog_priority'], 'Threshold ' . $thold_id . ' has been acknowledged. Additional Comments: ' . $desc);
|
|
}
|
|
|
|
$status = 99;
|
|
|
|
thold_log(
|
|
[
|
|
'type' => 99,
|
|
'time' => time(),
|
|
'host_id' => $thold_data['host_id'],
|
|
'local_graph_id' => $thold_data['local_graph_id'],
|
|
'threshold_id' => $thold_id,
|
|
'threshold_value' => '',
|
|
'current' => $thold_data['lastread'],
|
|
'status' => $status,
|
|
'description' => 'Threshold Name ' . $thold_data['name_cache'] . ' has been acknowledged. Additional Comments: "' . $desc . '"',
|
|
'emails' => '',
|
|
'bcc_emails' => ''
|
|
]
|
|
);
|
|
|
|
cacti_log('Threshold TH[' . $thold_id . '] has been acknowledged. Additional Comments: ' . $desc);
|
|
}
|
|
|
|
function thold_cdef_get_usable() {
|
|
$cdef_items = db_fetch_assoc('SELECT *
|
|
FROM cdef_items
|
|
WHERE value = "CURRENT_DATA_SOURCE"
|
|
ORDER BY cdef_id');
|
|
|
|
$cdef_usable = [];
|
|
|
|
if (cacti_sizeof($cdef_items)) {
|
|
foreach ($cdef_items as $cdef_item) {
|
|
$cdef_usable[] = $cdef_item['cdef_id'];
|
|
}
|
|
}
|
|
|
|
return $cdef_usable;
|
|
}
|
|
|
|
function thold_cdef_select_usable_names() {
|
|
$ids = thold_cdef_get_usable();
|
|
$cdefs = db_fetch_assoc('SELECT id, name FROM cdef');
|
|
|
|
$cdef_names[0] = '';
|
|
|
|
if (cacti_sizeof($cdefs)) {
|
|
foreach ($cdefs as $cdef) {
|
|
if (in_array($cdef['id'], $ids, true)) {
|
|
$cdef_names[$cdef['id']] = $cdef['name'];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $cdef_names;
|
|
}
|
|
|
|
function thold_build_cdef($cdef, $value, $local_data_id, $data_template_rrd_id) {
|
|
if ($value == '') {
|
|
$value = 0;
|
|
}
|
|
|
|
$oldvalue = $value;
|
|
|
|
$cdefs = db_fetch_assoc_prepared('SELECT *
|
|
FROM cdef_items
|
|
WHERE cdef_id = ?
|
|
ORDER BY sequence',
|
|
[$cdef]);
|
|
|
|
$cdef_array = [];
|
|
|
|
if (cacti_sizeof($cdefs)) {
|
|
foreach ($cdefs as $cdef) {
|
|
$prev_value = $cdef['value'];
|
|
|
|
if ($cdef['type'] == 4) {
|
|
$found = false;
|
|
$cdef['type'] = 6;
|
|
|
|
if ($cdef['value'] != '') {
|
|
if (strpos($cdef['value'], 'CURRENT_DATA_SOURCE') !== false) {
|
|
$cdef['value'] = str_replace('CURRENT_DATA_SOURCE', $oldvalue, $cdef['value']);
|
|
$found = true;
|
|
}
|
|
|
|
if (strpos($cdef['value'], 'CURRENT_GRAPH_MAXIMUM_VALUE') !== false) {
|
|
$cdef['value'] = str_replace('CURRENT_GRAPH_MAXIMUM_VALUE', get_current_value($local_data_id, 'upper_limit'), $cdef['value']);
|
|
$found = true;
|
|
}
|
|
|
|
if (strpos($cdef['value'], 'CURRENT_GRAPH_MINIMUM_VALUE') !== false) {
|
|
$cdef['value'] = str_replace('CURRENT_GRAPH_MINIMUM_VALUE', get_current_value($local_data_id, 'lower_limit'), $cdef['value']);
|
|
$found = true;
|
|
}
|
|
|
|
if (strpos($cdef['value'], 'CURRENT_DS_MINIMUM_VALUE') !== false) {
|
|
$cdef['value'] = str_replace('CURRENT_DS_MINIMUM_VALUE', get_current_value($local_data_id, 'rrd_minimum'), $cdef['value']);
|
|
$found = true;
|
|
}
|
|
|
|
if (strpos($cdef['value'], 'CURRENT_DS_MAXIMUM_VALUE') !== false) {
|
|
$cdef['value'] = str_replace('CURRENT_DS_MAXIMUM_VALUE', get_current_value($local_data_id, 'rrd_maximum'), $cdef['value']);
|
|
$found = true;
|
|
}
|
|
|
|
if (strpos($cdef['value'], 'VALUE_OF_HDD_TOTAL') !== false) {
|
|
$cdef['value'] = str_replace('VALUE_OF_HDD_TOTAL', get_current_value($local_data_id, 'hdd_total'), $cdef['value']);
|
|
$found = true;
|
|
}
|
|
|
|
if (strpos($cdef['value'], 'ALL_DATA_SOURCES_NODUPS') !== false || strpos($cdef['value'], 'ALL_DATA_SOURCES_DUPS') !== false) {
|
|
$found = true;
|
|
$total = 0;
|
|
|
|
$all_dsns = db_fetch_assoc_prepared('SELECT data_source_name
|
|
FROM data_template_rrd
|
|
WHERE local_data_id = ?',
|
|
[$local_data_id]);
|
|
|
|
if (cacti_sizeof($all_dsns)) {
|
|
foreach ($all_dsns as $dsn) {
|
|
$total += get_current_value($local_data_id, $dsn['data_source_name']);
|
|
}
|
|
}
|
|
|
|
$cdef['value'] = str_replace('ALL_DATA_SOURCES_NODUPS', $total, $cdef['value']);
|
|
$cdef['value'] = str_replace('ALL_DATA_SOURCES_DUPS', $total, $cdef['value']);
|
|
}
|
|
}
|
|
|
|
if (!$found) {
|
|
cacti_log('WARNING: Issues with CDEF property: ' . $cdef['value'] . ', CDEF ID: ' . $cdef['id'] . ', Returning Original Data: ' . $oldvalue, false, 'THOLD', POLLER_VERBOSITY_MEDIUM);
|
|
|
|
return $oldvalue;
|
|
|
|
break;
|
|
}
|
|
} elseif ($cdef['type'] == 6) {
|
|
if ($cdef['value'] != '') {
|
|
$regresult = preg_match('/^\|query_([A-Za-z0-9_]+)\|$/', $cdef['value'], $matches);
|
|
|
|
if ($regresult > 0) {
|
|
$cdef['value'] = db_fetch_cell_prepared('SELECT hsc.field_value
|
|
FROM data_local AS dl
|
|
INNER JOIN host_snmp_cache AS hsc
|
|
ON hsc.host_id = dl.host_id
|
|
AND hsc.snmp_query_id = dl.snmp_query_id
|
|
AND hsc.snmp_index = dl.snmp_index
|
|
WHERE dl.id = ?
|
|
AND hsc.field_name = ?',
|
|
[$local_data_id, $matches[1]]);
|
|
|
|
if ($cdef['value'] == '' || !is_numeric($cdef['value'])) {
|
|
$cdef['value'] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$cdef_array[] = $cdef;
|
|
|
|
if ($cdef['type'] == 6 && !is_numeric($cdef['value'])) {
|
|
cacti_log("WARNING: Value for Data ID $local_data_id is not numeric:'" . $cdef['value'] . "', Previous Value was:'" . $prev_value . "'", false, 'THOLD', POLLER_VERBOSITY_MEDIUM);
|
|
}
|
|
}
|
|
}
|
|
|
|
$x = cacti_count($cdef_array);
|
|
|
|
if ($x == 0) {
|
|
return $oldvalue;
|
|
}
|
|
|
|
$stack = []; // operation stack for RPN
|
|
array_push($stack, $cdef_array[0]); // first one always goes on
|
|
$cursor = 1; // current pointer through RPN operations list
|
|
|
|
while ($cursor < $x) {
|
|
$type = $cdef_array[$cursor]['type'];
|
|
|
|
switch($type) {
|
|
case 6:
|
|
array_push($stack, $cdef_array[$cursor]);
|
|
|
|
break;
|
|
case 2:
|
|
// this is a binary operation. pop two values, and then use them.
|
|
$v1 = thold_expression_rpn_pop($stack);
|
|
$v2 = thold_expression_rpn_pop($stack);
|
|
|
|
$result = thold_rpn($v2['value'], $v1['value'], $cdef_array[$cursor]['value'], $local_data_id);
|
|
|
|
// put the result back on the stack.
|
|
array_push($stack, ['type' => 6, 'value' => $result]);
|
|
|
|
break;
|
|
default:
|
|
cacti_log('Unknown RPN type: ' . $cdef_array[$cursor]['type'], false, 'THOLD', POLLER_VERBOSITY_MEDIUM);
|
|
|
|
return ($oldvalue);
|
|
|
|
break;
|
|
}
|
|
|
|
$cursor++;
|
|
}
|
|
|
|
return $stack[0]['value'];
|
|
}
|
|
|
|
function thold_rpn($x, $y, $z, $local_data_id = 0) {
|
|
if (empty($x) || $x == 'U') {
|
|
$x = 0;
|
|
}
|
|
|
|
if (empty($y) || $y == 'U') {
|
|
$y = 0;
|
|
}
|
|
|
|
if (!is_numeric($x)) {
|
|
cacti_log("WARNING: Erroneous CDEF logic, the first value should be numeric, but is '$x'. Data ID $local_data_id", false, 'THOLD');
|
|
|
|
return '';
|
|
}
|
|
|
|
if (!is_numeric($y)) {
|
|
cacti_log("WARNING: Erroneous CDEF logic, the second value should be numeric, but is '$y'. Data ID $local_data_id", false, 'THOLD');
|
|
|
|
return '';
|
|
}
|
|
|
|
switch ($z) {
|
|
case 1:
|
|
return $x + $y;
|
|
|
|
break;
|
|
case 2:
|
|
return $x - $y;
|
|
|
|
break;
|
|
case 3:
|
|
return $x * $y;
|
|
|
|
break;
|
|
case 4:
|
|
if ($y == 0) {
|
|
return (-1);
|
|
}
|
|
|
|
return $x / $y;
|
|
|
|
break;
|
|
case 5:
|
|
return $x % $y;
|
|
|
|
break;
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
function delete_old_thresholds() {
|
|
$tholds = db_fetch_assoc('SELECT td.id, td.data_template_rrd_id, td.local_data_id
|
|
FROM thold_data AS td
|
|
LEFT JOIN data_template_rrd AS dtr
|
|
ON dtr.id=td.data_template_rrd_id
|
|
WHERE dtr.local_data_id IS NULL');
|
|
|
|
if (cacti_sizeof($tholds)) {
|
|
foreach ($tholds as $thold_data) {
|
|
plugin_thold_log_changes($thold_data['id'], 'deleted', ['message' => 'Auto-delete due to Data Source removal']);
|
|
|
|
thold_api_thold_remove($thold_data['id']);
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_api_thold_remove($id) {
|
|
db_execute_prepared('DELETE FROM thold_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
db_execute_prepared('DELETE FROM plugin_thold_threshold_contact
|
|
WHERE thold_id = ?',
|
|
[$id]);
|
|
|
|
db_execute_prepared('DELETE FROM plugin_thold_daemon_data
|
|
WHERE id = ?',
|
|
[$id]);
|
|
}
|
|
|
|
function thold_api_thold_template_remove($id) {
|
|
db_execute_prepared('DELETE FROM thold_template
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
db_execute_prepared('DELETE FROM plugin_thold_template_contact
|
|
WHERE template_id = ?',
|
|
[$id]);
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET thold_template_id = 0, template_enabled = "off"
|
|
WHERE thold_template_id = ?',
|
|
[$id]);
|
|
}
|
|
|
|
function thold_rrd_last($local_data_id) {
|
|
$last_time_entry = @rrdtool_execute('last ' . trim(get_data_source_path($local_data_id, true)), false, RRDTOOL_OUTPUT_STDOUT);
|
|
|
|
return trim($last_time_entry);
|
|
}
|
|
|
|
function get_current_value($local_data_id, $data_template_rrd_id, $cdef = 0) {
|
|
// get the information to populate into the rrd files
|
|
if (function_exists('boost_check_correct_enabled') && boost_check_correct_enabled()) {
|
|
boost_process_poller_output($local_data_id);
|
|
}
|
|
|
|
$last_time_entry = thold_rrd_last($local_data_id);
|
|
|
|
// This should fix and 'did you really mean month 899 errors', this is because your RRD has not polled yet
|
|
if ($last_time_entry == -1) {
|
|
$last_time_entry = time();
|
|
}
|
|
|
|
$data_template_data = db_fetch_row_prepared('SELECT *
|
|
FROM data_template_data
|
|
WHERE local_data_id = ?',
|
|
[$local_data_id]);
|
|
|
|
$step = $data_template_data['rrd_step'];
|
|
|
|
// Round down to the nearest 100
|
|
$last_time_entry = (intval($last_time_entry / 100) * 100) - $step;
|
|
$last_needed = $last_time_entry + $step;
|
|
|
|
$result = rrdtool_function_fetch($local_data_id, trim($last_time_entry), trim($last_needed));
|
|
|
|
// Return Blank if the data source is not found (Newly created?)
|
|
if (!isset($result['data_source_names'])) {
|
|
return 0;
|
|
}
|
|
|
|
$idx = array_search($data_template_rrd_id, $result['data_source_names'], true);
|
|
|
|
// Return Blank if the value was not found (Cache Cleared?)
|
|
|
|
if (!isset($result['values']) || $idx === null || !cacti_sizeof($result['values'][$idx])) {
|
|
return 0;
|
|
}
|
|
|
|
$value = array_values($result['values'][$idx])[0];
|
|
|
|
if ($cdef > 0) {
|
|
$value = thold_build_cdef($cdef, $value, $local_data_id, $data_template_rrd_id);
|
|
}
|
|
|
|
return round($value, 4);
|
|
}
|
|
|
|
function thold_get_ref_values($local_data_id, $data_source_name, $current_time, $prev_time, $avg_of_cf) {
|
|
$data = thold_get_rrd_statistics($local_data_id, $current_time, $prev_time, $avg_of_cf);
|
|
|
|
if (!isset($data[$data_source_name])) {
|
|
return false;
|
|
}
|
|
|
|
return $data[$data_source_name];
|
|
}
|
|
|
|
/**
|
|
* thold_check_exception_periods
|
|
*
|
|
* @to-do: This function should check 'globally' declared exceptions, like
|
|
* holidays etc., as well as exceptions bound to the specific $local_data_id. $local_data_id
|
|
* should inherit exceptions that are assigned on the higher level (i.e. device).
|
|
*
|
|
* @param mixed $local_data_id
|
|
* @param mixed $ref_time
|
|
* @param mixed $ref_range
|
|
*/
|
|
function thold_check_exception_periods($local_data_id, $ref_time, $ref_range) {
|
|
// TO-DO
|
|
// Check if the reference time falls into global exceptions
|
|
// Check if the current time falls into global exceptions
|
|
// Check if $local_data_id + $data_template_rrd_id have an exception (again both reference time and current time)
|
|
// Check if there are inheritances
|
|
|
|
// More on the exception concept:
|
|
// -Exceptions can be one time and recurring
|
|
// -Exceptions can be global and assigned to:
|
|
// -templates
|
|
// -devices
|
|
// -data sources
|
|
//
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* thold_check_baseline -
|
|
* Should be called after hard limits have been checked and only when they are OK
|
|
*
|
|
* The function "goes back in time" $ref_time seconds and retrieves the data
|
|
* for $ref_range seconds. Then it finds minimum and maximum values and calculates
|
|
* allowed deviations from those values.
|
|
*
|
|
* @param $local_data_id - the data source to check the data
|
|
* @param $data_source_name - the data source name to gather data from
|
|
* @param $current_value - the current data source value
|
|
* @param $thold_data - The thold data structure
|
|
*
|
|
* @return integer - integer value that indicates status
|
|
* -2 if the exception is active
|
|
* -1 if the reference value is not available
|
|
* 0 if the current value is within the boundaries
|
|
* 1 if the current value is below the calculated threshold
|
|
* 2 if the current value is above the calculated threshold
|
|
*/
|
|
function thold_check_baseline($local_data_id, $data_source_name, $current_value, &$thold_data) {
|
|
global $debug;
|
|
|
|
$now = time();
|
|
|
|
$poller_interval = read_config_option('poller_interval');
|
|
|
|
if (empty($poller_interval)) {
|
|
$poller_interval = 300;
|
|
}
|
|
|
|
$current_time = time() - $poller_interval;
|
|
$prev_time = $current_time - $thold_data['bl_ref_time_range'];
|
|
$avg_of_cf = '';
|
|
|
|
if ($thold_data['bl_type'] < 4) {
|
|
if ($thold_data['bl_ref_time_range'] > 86400 * 2) {
|
|
$current_time = $prev_time + 86400;
|
|
} elseif ($thold_data['bl_ref_time_range'] > 3600 * 2) {
|
|
$current_time = $prev_time + 3600;
|
|
} else {
|
|
$current_time = $prev_time;
|
|
}
|
|
} elseif ($thold_data['bl_type'] == 5 || $thold_data['bl_type'] == 7) {
|
|
$avg_of_cf = $thold_data['bl_cf'];
|
|
}
|
|
|
|
$ref_values = thold_get_ref_values($thold_data['local_data_id'], $data_source_name, $current_time, $prev_time, $avg_of_cf);
|
|
|
|
if ($ref_values === false || cacti_sizeof($ref_values) == 0) {
|
|
cacti_log(sprintf('WARNING: RRDtool was unable to return any reference values to TH[%s]', $thold_data['id']), false, 'THOLD');
|
|
|
|
return -1;
|
|
}
|
|
|
|
$ref_value_min = 0;
|
|
$ref_value_max = 0;
|
|
$ref_value_avg = 0;
|
|
$ref_value_last = 0;
|
|
$ref_value_cfa = 0;
|
|
|
|
if (isset($ref_values['MIN'])) {
|
|
$ref_value_min = $ref_values['MIN'];
|
|
}
|
|
|
|
if (isset($ref_values['MAX'])) {
|
|
$ref_value_max = $ref_values['MAX'];
|
|
}
|
|
|
|
if (isset($ref_values['AVG'])) {
|
|
$ref_value_avg = $ref_values['AVG'];
|
|
}
|
|
|
|
if (isset($ref_values['LAST'])) {
|
|
$ref_value_last = $ref_values['LAST'];
|
|
}
|
|
|
|
if (isset($ref_values['CFA'])) {
|
|
$ref_value_cfa = $ref_values['CFA'];
|
|
}
|
|
|
|
if ($thold_data['cdef'] > 0 && $thold_data['data_type'] == 1) {
|
|
if ($ref_value_min == '-nan' || $ref_value_max == '-nan' || $ref_value_avg == '-nan') {
|
|
cacti_log("WARNING: CDEF values are -nan: MIN $ref_value_min MAX $ref_value_max AVG $ref_value_avg LAST $ref_value_last " .
|
|
" Threshold {$thold_data['id']}:{$thold_data['name_cache']} :" . __FILE__ . ' ' . __FUNCTION__ . ':' . __LINE__, false, 'THOLD');
|
|
}
|
|
|
|
$ref_value_min = thold_build_cdef($thold_data['cdef'], $ref_value_min, $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$ref_value_max = thold_build_cdef($thold_data['cdef'], $ref_value_max, $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$ref_value_avg = thold_build_cdef($thold_data['cdef'], $ref_value_avg, $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$ref_value_last = thold_build_cdef($thold_data['cdef'], $ref_value_last, $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
$ref_value_cfa = thold_build_cdef($thold_data['cdef'], $ref_value_cfa, $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
}
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET bl_reference_min = ?, bl_reference_max = ?, bl_reference_avg = ?, bl_reference_last = ?
|
|
WHERE id = ?',
|
|
[$ref_value_min, $ref_value_max, $ref_value_avg, $ref_value_last, $thold_data['id']]);
|
|
|
|
$blt_low = '';
|
|
$blt_high = '';
|
|
|
|
// setup for CF based deviations
|
|
switch($thold_data['bl_cf']) {
|
|
case 'AVG':
|
|
$ref_value = $ref_value_avg;
|
|
|
|
break;
|
|
case 'MIN':
|
|
$ref_value = $ref_value_min;
|
|
|
|
break;
|
|
case 'MAX':
|
|
$ref_value = $ref_value_max;
|
|
|
|
break;
|
|
case 'LAST':
|
|
$ref_value = $ref_value_last;
|
|
|
|
break;
|
|
}
|
|
|
|
/**
|
|
* Baseline types
|
|
*
|
|
* 0 - % Deviation of Min/Max from Time in the past 'LAST'
|
|
* 1 - % Deviation of CF in the past
|
|
* 2 - Absolute Value Deviation of Min/Max from Time in the past
|
|
* 3 - Absolute Value Deviation of CF from Time in the past
|
|
* 4 - % Deviation from Floating Average of over the time period
|
|
* 5 - % Deviation from Floating Average of CF over time period
|
|
* 6 - Absolute Value Deviation of Floating Average over the time period
|
|
* 7 - Absolute Value Deviation of CF over the time period
|
|
*/
|
|
if ($thold_data['bl_type'] == 0) {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value_min)) {
|
|
$blt_low = $ref_value_min - (abs($ref_value_min) * $thold_data['bl_pct_down'] / 100);
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value_max)) {
|
|
$blt_high = $ref_value_max + (abs($ref_value_max) * $thold_data['bl_pct_up'] / 100);
|
|
}
|
|
} elseif ($thold_data['bl_type'] == 1) {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value)) {
|
|
$blt_low = $ref_value - (abs($ref_value) * $thold_data['bl_pct_down'] / 100);
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value)) {
|
|
$blt_high = $ref_value + (abs($ref_value) * $thold_data['bl_pct_up'] / 100);
|
|
}
|
|
} elseif ($thold_data['bl_type'] == 2) {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value_min)) {
|
|
$blt_low = $ref_value_min - $thold_data['bl_pct_down'];
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value_max)) {
|
|
$blt_high = $ref_value_max + $thold_data['bl_pct_up'];
|
|
}
|
|
} elseif ($thold_data['bl_type'] == 3) {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value)) {
|
|
$blt_low = $ref_value - $thold_data['bl_pct_down'];
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value)) {
|
|
$blt_high = $ref_value + $thold_data['bl_pct_up'];
|
|
}
|
|
} elseif ($thold_data['bl_type'] == 4) {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value_avg)) {
|
|
$blt_low = $ref_value_avg - (abs($ref_value_avg) * $thold_data['bl_pct_down'] / 100);
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value_avg)) {
|
|
$blt_high = $ref_value_avg + (abs($ref_value_avg) * $thold_data['bl_pct_up'] / 100);
|
|
}
|
|
} elseif ($thold_data['bl_type'] == 5) {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value_avg)) {
|
|
$blt_low = $ref_value_avg - (abs($ref_value_avg) * $thold_data['bl_pct_down'] / 100);
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value_avg)) {
|
|
$blt_high = $ref_value_avg + (abs($ref_value_avg) * $thold_data['bl_pct_up'] / 100);
|
|
}
|
|
} elseif ($thold_data['bl_type'] == 6) {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value_avg)) {
|
|
$blt_low = $ref_value_avg - $thold_data['bl_pct_down'];
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value_avg)) {
|
|
$blt_high = $ref_value_avg + $thold_data['bl_pct_up'];
|
|
}
|
|
} else {
|
|
if ($thold_data['bl_pct_down'] != '' && is_numeric($ref_value_cfa)) {
|
|
$blt_low = $ref_value_cfa - $thold_data['bl_pct_down'];
|
|
}
|
|
|
|
if ($thold_data['bl_pct_up'] != '' && is_numeric($ref_value_cfa)) {
|
|
$blt_high = $ref_value_cfa + $thold_data['bl_pct_up'];
|
|
}
|
|
}
|
|
|
|
// Cache the calculated or empty values
|
|
$thold_data['thold_low'] = $blt_low;
|
|
$thold_data['thold_hi'] = $blt_high;
|
|
$thold_data['bl_thold_valid'] = 0;
|
|
|
|
$failed = 0;
|
|
|
|
// Check low boundary
|
|
if ($blt_low != '' && $current_value < $blt_low) {
|
|
$failed = 1;
|
|
}
|
|
|
|
// Check up boundary
|
|
if ($failed == 0 && $blt_high != '' && $current_value > $blt_high) {
|
|
$failed = 2;
|
|
}
|
|
|
|
if ($debug) {
|
|
print 'Local Data Id: ' . $local_data_id . ':' . $thold_data['data_template_rrd_id'] . "\n";
|
|
print 'Ref. values count: ' . (isset($ref_values) ? count($ref_values) : 'N/A') . "\n";
|
|
print 'Ref. value (min): ' . (isset($ref_value_min) ? $ref_value_min : 'N/A') . "\n";
|
|
print 'Ref. value (max): ' . (isset($ref_value_max) ? $ref_value_max : 'N/A') . "\n";
|
|
print 'Cur. value: ' . $current_value . "\n";
|
|
print 'Low bl thresh: ' . (isset($blt_low) ? $blt_low : 'N/A') . "\n";
|
|
print 'High bl thresh: ' . (isset($blt_high) ? $blt_high : 'N/A') . "\n";
|
|
print 'Check against baseline: ';
|
|
|
|
switch($failed) {
|
|
case 0:
|
|
print 'OK';
|
|
|
|
break;
|
|
case 1:
|
|
print 'FAIL: Below baseline threshold!';
|
|
|
|
break;
|
|
case 2:
|
|
print 'FAIL: Above baseline threshold!';
|
|
|
|
break;
|
|
}
|
|
print "\n";
|
|
print "------------------\n";
|
|
}
|
|
|
|
return $failed;
|
|
}
|
|
|
|
function get_bl_type($type, $cf) {
|
|
global $bl_types;
|
|
|
|
switch($type) {
|
|
case '0':
|
|
case '2':
|
|
case '4':
|
|
case '6':
|
|
return str_replace(['Deviation', 'Absolute'], ['Dev', 'Abs'], $bl_types[$type]);
|
|
|
|
break;
|
|
case '1':
|
|
return __('%% Dev [TIP:%s]', $cf, 'thold');
|
|
|
|
break;
|
|
case '3':
|
|
return __('Abs Val [TIP:%s]', $cf, 'thold');
|
|
|
|
break;
|
|
case '5':
|
|
return __('%%% Dev [AOT:%s]', $cf, 'thold');
|
|
|
|
break;
|
|
case '7':
|
|
return __('Abs Val [AOT:%s]', $cf, 'thold');
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
function thold_create_new_graph_from_template() {
|
|
if (!isset_request_var('host_id')) {
|
|
$device_id = 0;
|
|
} else {
|
|
$device_id = get_filter_request_var('host_id');
|
|
}
|
|
|
|
if (isset_request_var('save_component_graph')) {
|
|
// summarize the 'create graph from host template/snmp index' stuff into an array
|
|
foreach ($_POST as $var => $val) {
|
|
if (preg_match('/^cg_(\d+)$/', $var, $matches)) {
|
|
$selected_graphs['cg'][$matches[1]][$matches[1]] = true;
|
|
} elseif (preg_match('/^cg_g$/', $var)) {
|
|
if (get_request_var('cg_g') > 0) {
|
|
$selected_graphs['cg'][get_request_var('cg_g')][get_request_var('cg_g')] = true;
|
|
}
|
|
} elseif (preg_match('/^sg_(\d+)_([a-f0-9]{32})$/', $var, $matches)) {
|
|
$selected_graphs['sg'][$matches[1]][get_nfilter_request_var('sgg_' . $matches[1])][$matches[2]] = true;
|
|
}
|
|
}
|
|
|
|
if (!isset_request_var('host_template_id')) {
|
|
$host_template_id = 0;
|
|
} else {
|
|
$host_template_id = get_filter_request_var('host_template_id');
|
|
}
|
|
|
|
if (isset($selected_graphs)) {
|
|
html_graph_new_graphs('thold.php', $device_id, $host_template_id, $selected_graphs);
|
|
exit;
|
|
}
|
|
} elseif (isset_request_var('save_component_new_graphs')) {
|
|
thold_new_graphs_save($device_id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* thold_display_to_raw - Converts a displayed number to a raw
|
|
* numeric value. This function converts number like '100M'
|
|
* to the raw number 100,000,000, etc.
|
|
*
|
|
* Supported Units
|
|
*
|
|
* Unit Expression
|
|
* ---- -------------------------------------
|
|
* f Fermo (10e-12)
|
|
* p Pico (10e-9)
|
|
* u Micro (10e-6)
|
|
* m Milli (10e-3)
|
|
* K Killo (10e3)
|
|
* M Mega (10e6)
|
|
* G Giga (10e9)
|
|
* T Terra (10e12)
|
|
* P Peta (10e15)
|
|
* E Exa (10e18)
|
|
* Z Zeta (10e21)
|
|
* Y Yota (10e24)
|
|
*
|
|
* @param mixed $number
|
|
* @param mixed $field_name
|
|
*/
|
|
function thold_display_to_raw($number, $field_name) {
|
|
$number = trim($number);
|
|
|
|
$_SESSION['sess_field_values'][$field_name] = $number;
|
|
|
|
$suffix = substr($number, -1);
|
|
|
|
// if the number is numeric just return
|
|
if (is_numeric($suffix)) {
|
|
return $number;
|
|
}
|
|
|
|
$number = trim(substr($number, 0, -1));
|
|
|
|
if (!is_numeric($number)) {
|
|
$_SESSION['sess_error_fields'][$field_name] = $field_name;
|
|
raise_message(3);
|
|
|
|
return false;
|
|
}
|
|
|
|
switch($suffix) {
|
|
case 'f':
|
|
return $number * 1e-15;
|
|
|
|
break;
|
|
case 'p':
|
|
return $number * 1e-9;
|
|
|
|
break;
|
|
case 'u':
|
|
return $number * 1e-6;
|
|
|
|
break;
|
|
case 'm':
|
|
return $number * 1e-3;
|
|
|
|
break;
|
|
case 'K':
|
|
return $number * 1e3;
|
|
|
|
break;
|
|
case 'M':
|
|
return $number * 1e6;
|
|
|
|
break;
|
|
case 'G':
|
|
return $number * 1e9;
|
|
|
|
break;
|
|
case 'T':
|
|
return $number * 1e12;
|
|
|
|
break;
|
|
case 'P':
|
|
return $number * 1e15;
|
|
|
|
break;
|
|
case 'E':
|
|
return $number * 1e18;
|
|
|
|
break;
|
|
case 'Z':
|
|
return $number * 1e21;
|
|
|
|
break;
|
|
case 'Y':
|
|
return $number * 1e24;
|
|
|
|
break;
|
|
default:
|
|
$_SESSION['sess_error_fields'][$field_name] = $field_name;
|
|
raise_message(3);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* thold_display_to_raw - Converts a displayed number to a raw
|
|
* numeric value. This function converts number like '100M'
|
|
* to the raw number 100,000,000, etc.
|
|
*
|
|
* Supported Units
|
|
*
|
|
* Unit Expression
|
|
* ---- -------------------------------------
|
|
* f Fermo (10e-12)
|
|
* p Pico (10e-9)
|
|
* u Micro (10e-6)
|
|
* m Milli (10e-3)
|
|
* K Killo (10e3)
|
|
* M Mega (10e6)
|
|
* G Giga (10e9)
|
|
* T Terra (10e12)
|
|
* P Peta (10e15)
|
|
* E Exa (10e18)
|
|
* Z Zeta (10e21)
|
|
* Y Yota (10e24)
|
|
*
|
|
* @param mixed $number
|
|
*/
|
|
function thold_raw_to_display($number) {
|
|
if ($number != '') {
|
|
$number = trim($number);
|
|
}
|
|
|
|
if (!is_numeric($number)) {
|
|
return false;
|
|
}
|
|
|
|
if ($number == 0) {
|
|
return trim($number);
|
|
}
|
|
|
|
if ($number > 0) {
|
|
$multiplier = 1;
|
|
} else {
|
|
$multiplier = -1;
|
|
}
|
|
|
|
$number = abs($number);
|
|
$suffix = '';
|
|
|
|
if ($number > 1) {
|
|
$pattern = 'KMGTPEZY';
|
|
$count = 0;
|
|
|
|
while ($number >= 1e3) {
|
|
$count++;
|
|
$number /= 1e3;
|
|
}
|
|
|
|
if ($count > 0) {
|
|
$suffix = $pattern[$count - 1];
|
|
}
|
|
} else {
|
|
$pattern = 'mupf';
|
|
$count = 0;
|
|
|
|
while ($number < 1) {
|
|
$count++;
|
|
$number *= 1e3;
|
|
}
|
|
|
|
if ($count > 0) {
|
|
$suffix = $pattern[$count - 1];
|
|
}
|
|
}
|
|
|
|
return trim(($number * $multiplier) . $suffix);
|
|
}
|
|
|
|
function save_thold() {
|
|
global $banner;
|
|
|
|
$data_query_id = get_filter_request_var('data_query_id');
|
|
$data_template_id = get_filter_request_var('data_template_id');
|
|
$graph_template_id = get_filter_request_var('graph_template_id');
|
|
$host_template_id = get_filter_request_var('host_template_id');
|
|
$thold_template_id = get_filter_request_var('thold_template_id');
|
|
|
|
if (isset_request_var('save_component_new_graphs')) {
|
|
// Correct issue where host_id variables comes back as an array
|
|
if (isset_request_var('host_id')) {
|
|
if (is_array(get_nfilter_request_var('host_id'))) {
|
|
$temp = get_nfilter_request_var('host_id');
|
|
|
|
foreach ($temp as $t) {
|
|
set_request_var('host_id', input_validate_input_number($t));
|
|
}
|
|
}
|
|
} else {
|
|
$banner = __('The Device ID was not set while trying to create Graph and Threshold', 'thold');
|
|
thold_raise_message($banner, MESSAGE_LEVEL_ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
$device_id = get_filter_request_var('host_id');
|
|
|
|
if (isset_request_var('thold_template_id')) {
|
|
$template = db_fetch_row_prepared('SELECT *
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[get_filter_request_var('thold_template_id')]);
|
|
|
|
if (!sizeof($template)) {
|
|
$banner = __('The Threshold Template ID was not found while trying to create Graph and Threshold', 'thold');
|
|
thold_raise_message($banner, MESSAGE_LEVEL_ERROR);
|
|
cacti_log('ERROR: The Threshold Template ID was not found', false, 'THOLD');
|
|
|
|
return false;
|
|
}
|
|
} else {
|
|
$banner = __('The Threshold Template ID was not set while trying to create Graph and Threshold', 'thold');
|
|
thold_raise_message($banner, MESSAGE_LEVEL_ERROR);
|
|
cacti_log('ERROR: The Threshold Template ID not set for save', false, 'THOLD');
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* attempt to see if the graph already exists for this thold
|
|
* if it's template based.
|
|
*/
|
|
if (isset_request_var('type_id') && get_nfilter_request_var('type_id') == 'template') {
|
|
if (get_filter_request_var('data_query_id') > 0) {
|
|
$local_graph_id = db_fetch_cell_prepared('SELECT gl.id
|
|
FROM graph_local AS gl
|
|
INNER JOIN snmp_query_graph AS sqg
|
|
ON sqg.snmp_query_id = gl.snmp_query_id
|
|
AND sqg.graph_template_id = gl.graph_template_id
|
|
WHERE sqg.id = ?
|
|
AND gl.host_id = ?
|
|
AND gl.snmp_query_id = ?
|
|
AND gl.snmp_index = ?
|
|
ORDER BY id ASC
|
|
LIMIT 1',
|
|
[
|
|
get_filter_request_var('graph_template_id'),
|
|
get_filter_request_var('host_id'),
|
|
get_filter_request_var('data_query_id'),
|
|
get_request_var('snmp_index')
|
|
]
|
|
);
|
|
|
|
if ($local_graph_id > 0) {
|
|
$graph_template_id = db_fetch_cell_prepared('SELECT graph_template_id
|
|
FROM graph_local
|
|
WHERE id = ?',
|
|
[$local_graph_id]);
|
|
|
|
set_request_var('graph_template_id', $graph_template_id);
|
|
}
|
|
} else {
|
|
$local_graph_id = db_fetch_cell_prepared('SELECT id
|
|
FROM graph_local
|
|
WHERE graph_template_id = ?
|
|
AND host_id = ?
|
|
AND snmp_query_id = ?
|
|
AND snmp_index = ?
|
|
ORDER BY id ASC
|
|
LIMIT 1',
|
|
[
|
|
get_filter_request_var('graph_template_id'),
|
|
get_filter_request_var('host_id'),
|
|
get_filter_request_var('data_query_id'),
|
|
get_request_var('snmp_index')
|
|
]
|
|
);
|
|
}
|
|
|
|
if ($local_graph_id > 0) {
|
|
$local_data = db_fetch_row_prepared('SELECT dtr.id, dtr.local_data_id
|
|
FROM data_template_rrd AS dtr
|
|
INNER JOIN graph_templates_item AS gti
|
|
ON gti.task_item_id = dtr.id
|
|
AND gti.local_graph_id = ?',
|
|
[$local_graph_id]);
|
|
|
|
if (isset($local_data['local_data_id']) && $local_data['local_data_id'] > 0) {
|
|
set_request_var('local_graph_id', $local_graph_id);
|
|
set_request_var('local_data_id', $local_data['local_data_id']);
|
|
set_request_var('data_template_rrd_id', $local_data['id']);
|
|
}
|
|
}
|
|
|
|
set_request_var('thold_per_enabled', 'on');
|
|
}
|
|
|
|
if (!isset_request_var('local_graph_id')) {
|
|
$graph_array = thold_new_graphs_save($device_id);
|
|
|
|
if ($graph_array !== false) {
|
|
if (isset($graph_array['local_graph_id'])) {
|
|
set_request_var('local_graph_id', $graph_array['local_graph_id']);
|
|
}
|
|
|
|
if (empty($data_template_id)) {
|
|
$data_template_id = db_fetch_cell_prepared('SELECT data_template_id
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$thold_template_id]);
|
|
}
|
|
|
|
if (isset($graph_array['local_data_id'][$data_template_id])) {
|
|
set_request_var('local_data_id', $graph_array['local_data_id'][$data_template_id]);
|
|
}
|
|
|
|
$temp = db_fetch_cell_prepared('SELECT dtr.id
|
|
FROM data_template_rrd AS dtr
|
|
WHERE local_data_id = ?
|
|
AND data_source_name = ?',
|
|
[get_request_var('local_data_id'), $template['data_source_name']]);
|
|
|
|
set_request_var('data_template_rrd_id', $temp);
|
|
} else {
|
|
$banner = __('The Graph Creation failed for Threshold Template', 'thold');
|
|
thold_raise_message($banner, MESSAGE_LEVEL_ERROR);
|
|
cacti_log('ERROR: Graph Creation failed for Threshold Template', false, 'THOLD');
|
|
|
|
return false;
|
|
}
|
|
|
|
set_request_var('thold_per_enabled', 'on');
|
|
}
|
|
|
|
if (!isset_request_var('save_autocreate') || get_filter_request_var('save_autocreate') == 1) {
|
|
$autocreated = db_fetch_cell_prepared('SELECT COUNT(*)
|
|
FROM plugin_thold_host
|
|
WHERE host_id = ?
|
|
AND thold_template_id = ?',
|
|
[$device_id, $thold_template_id]);
|
|
|
|
if ($autocreated) {
|
|
$thold = db_fetch_cell_prepared('SELECT id
|
|
FROM thold_data
|
|
WHERE local_data_id = ?
|
|
AND local_graph_id = ?
|
|
AND data_template_rrd_id = ?
|
|
AND data_source_name = ?',
|
|
[
|
|
get_request_var('local_data_id'),
|
|
get_request_var('local_graph_id'),
|
|
get_request_var('data_template_rrd_id'),
|
|
$template['data_source_name']
|
|
]
|
|
);
|
|
|
|
if ($thold > 0) {
|
|
$banner = __('Threshold was Autocreated due to Device Template mapping', 'thold');
|
|
thold_raise_message($banner, MESSAGE_LEVEL_INFO);
|
|
|
|
return $thold;
|
|
}
|
|
}
|
|
|
|
set_request_var('thold_enabled', 'on');
|
|
}
|
|
}
|
|
|
|
if (isset_request_var('my_host_id')) {
|
|
$device_id = get_filter_request_var('my_host_id');
|
|
} else {
|
|
$device_id = get_filter_request_var('host_id');
|
|
}
|
|
|
|
$local_data_id = get_filter_request_var('local_data_id');
|
|
$local_graph_id = get_filter_request_var('local_graph_id');
|
|
$data_template_rrd_id = get_filter_request_var('data_template_rrd_id');
|
|
|
|
// In cases where a Graph can have multiple RRDtool data sources
|
|
// coming from different RRDfiles, we have to reset the local
|
|
// local_data_id to match the data_template_rrd_id
|
|
if (!empty($data_template_rrd_id)) {
|
|
$local_data_id = db_fetch_cell_prepared('SELECT local_data_id
|
|
FROM data_template_rrd
|
|
WHERE id = ?',
|
|
[$data_template_rrd_id]);
|
|
}
|
|
|
|
$template_enabled = isset_request_var('template_enabled') && get_nfilter_request_var('template_enabled') == 'on' ? 'on' : 'off';
|
|
$thold_per_enabled = isset_request_var('thold_per_enabled') && get_nfilter_request_var('thold_per_enabled') == 'on' ? 'on' : '';
|
|
|
|
if ($template_enabled == 'on') {
|
|
if ($local_graph_id > 0 && !is_thold_allowed_graph($local_graph_id)) {
|
|
$banner = __('Permission Denied', 'thold');
|
|
thold_raise_message($banner, MESSAGE_LEVEL_ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
if (get_request_var('id') > 0) {
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET template_enabled = "on", thold_per_enabled = ?
|
|
WHERE id = ?',
|
|
[$thold_per_enabled, get_request_var('id')]);
|
|
}
|
|
|
|
$data = db_fetch_row_prepared('SELECT id, thold_template_id
|
|
FROM thold_data
|
|
WHERE local_data_id = ?
|
|
AND data_template_rrd_id = ?',
|
|
[$local_data_id, $data_template_rrd_id]);
|
|
|
|
thold_template_update_threshold($data['id'], $data['thold_template_id']);
|
|
|
|
$banner = __('Record Updated', 'thold');
|
|
|
|
plugin_thold_log_changes($data['id'], 'modified', ['id' => $data['id'], 'template_enabled' => 'on']);
|
|
|
|
thold_raise_message($banner, MESSAGE_LEVEL_INFO);
|
|
|
|
return get_filter_request_var('id');
|
|
}
|
|
|
|
get_filter_request_var('thold_fail_trigger');
|
|
get_filter_request_var('thold_warning_fail_trigger');
|
|
|
|
get_filter_request_var('repeat_alert');
|
|
|
|
get_filter_request_var('thold_type');
|
|
|
|
get_filter_request_var('time_fail_trigger');
|
|
get_filter_request_var('time_fail_length');
|
|
get_filter_request_var('time_warning_fail_trigger');
|
|
get_filter_request_var('time_warning_fail_length');
|
|
|
|
get_filter_request_var('data_type');
|
|
get_filter_request_var('cdef');
|
|
|
|
get_filter_request_var('notify_warning');
|
|
get_filter_request_var('notify_alert');
|
|
|
|
get_filter_request_var('bl_type');
|
|
get_filter_request_var('bl_ref_time_range');
|
|
get_filter_request_var('bl_fail_trigger');
|
|
|
|
get_filter_request_var('syslog_facility');
|
|
get_filter_request_var('syslog_priority');
|
|
|
|
$save = [];
|
|
|
|
if ($thold_template_id > 0 && !isset_request_var('id')) {
|
|
$save = $template;
|
|
|
|
unset($save['id']);
|
|
unset($save['hash']);
|
|
unset($save['suggested_name']);
|
|
unset($save['data_source_id']);
|
|
unset($save['data_template_name']);
|
|
unset($save['data_source_friendly']);
|
|
unset($save['notify_templated']);
|
|
|
|
set_request_var('thold_enabled', 'on');
|
|
set_request_var('template_enabled', 'on');
|
|
}
|
|
|
|
if (isset_request_var('id')) {
|
|
$save['id'] = get_request_var('id');
|
|
} else {
|
|
$save['id'] = '0';
|
|
}
|
|
|
|
if (isset_request_var('snmp_event_category')) {
|
|
set_request_var('snmp_event_category', trim(str_replace(['\\', "'", '"'], '', get_nfilter_request_var('snmp_event_category'))));
|
|
}
|
|
|
|
if (isset_request_var('snmp_event_description')) {
|
|
set_request_var('snmp_event_description', trim(str_replace(['\\', "'", '"'], '', get_nfilter_request_var('snmp_event_description'))));
|
|
}
|
|
|
|
if (isset_request_var('snmp_event_severity')) {
|
|
get_filter_request_var('snmp_event_severity');
|
|
}
|
|
|
|
if (isset_request_var('snmp_event_warning_severity')) {
|
|
get_filter_request_var('snmp_event_warning_severity');
|
|
}
|
|
|
|
if (!empty($data_template_rrd_id)) {
|
|
$data_source_name = db_fetch_cell_prepared('SELECT data_source_name
|
|
FROM data_template_rrd
|
|
WHERE id = ?',
|
|
[$data_template_rrd_id]);
|
|
|
|
$data_source_info = db_fetch_row_prepared('SELECT data_template_id, data_source_name
|
|
FROM data_template_rrd
|
|
WHERE id = ?',
|
|
[$data_template_rrd_id]);
|
|
} elseif (!empty($local_graph_id) && empty($graph_template_id)) {
|
|
$graph_template_id = db_fetch_cell_prepared('SELECT graph_template_id
|
|
FROM graph_local
|
|
WHERE id = ?',
|
|
[$local_graph_id]);
|
|
}
|
|
|
|
$save['host_id'] = $device_id;
|
|
$save['data_template_rrd_id'] = $data_template_rrd_id;
|
|
$save['local_data_id'] = $local_data_id;
|
|
|
|
if ($thold_template_id == 0) {
|
|
$save['thold_enabled'] = 'on';
|
|
} else {
|
|
$save['thold_enabled'] = isset_request_var('thold_enabled') && get_request_var('thold_enabled') == 'on' ? 'on' : 'off';
|
|
}
|
|
|
|
$save['thold_per_enabled'] = isset_request_var('thold_per_enabled') && get_request_var('thold_per_enabled') == 'on' ? 'on' : '';
|
|
|
|
if ($thold_template_id > 0) {
|
|
$save['thold_template_id'] = $thold_template_id;
|
|
}
|
|
|
|
$save['exempt'] = isset_request_var('exempt') ? 'on' : '';
|
|
$save['repeat_alert'] = get_filter_request_var('repeat_alert');
|
|
$save['data_template_id'] = $data_source_info['data_template_id'];
|
|
$save['data_source_name'] = $data_source_info['data_source_name'];
|
|
|
|
// Acknowledgment
|
|
if (isset_request_var('acknowledgment')) {
|
|
switch(get_nfilter_request_var('acknowledgment')) {
|
|
case 'none':
|
|
$save['reset_ack'] = '';
|
|
$save['persist_ack'] = '';
|
|
|
|
break;
|
|
case 'reset_ack':
|
|
$save['reset_ack'] = 'on';
|
|
$save['persist_ack'] = '';
|
|
|
|
break;
|
|
case 'persist_ack':
|
|
$save['reset_ack'] = '';
|
|
$save['persist_ack'] = 'on';
|
|
|
|
break;
|
|
}
|
|
} else {
|
|
$save['reset_ack'] = '';
|
|
$save['persist_ack'] = '';
|
|
}
|
|
|
|
// Syslog Settings
|
|
$save['syslog_enabled'] = isset_request_var('syslog_enabled') ? 'on' : '';
|
|
$save['syslog_priority'] = get_request_var('syslog_priority');
|
|
$save['syslog_facility'] = get_request_var('syslog_facility');
|
|
|
|
// HRULE Settings
|
|
$save['thold_hrule_warning'] = get_nfilter_request_var('thold_hrule_warning');
|
|
$save['thold_hrule_alert'] = get_nfilter_request_var('thold_hrule_alert');
|
|
$save['skipscale'] = isset_request_var('skipscale') ? 'on' : '';
|
|
|
|
$save['restored_alert'] = isset_request_var('restored_alert') ? 'on' : '';
|
|
$save['thold_type'] = get_request_var('thold_type');
|
|
$save['template_enabled'] = isset_request_var('template_enabled') && get_nfilter_request_var('template_enabled') == 'on' ? 'on' : 'off';
|
|
|
|
// High / Low
|
|
$save['thold_hi'] = trim_round_request_var('thold_hi', 4, 'thold_hi');
|
|
$save['thold_low'] = trim_round_request_var('thold_low', 4, 'thold_low');
|
|
$save['thold_fail_trigger'] = isempty_request_var('thold_fail_trigger') ? read_config_option('alert_trigger') : get_nfilter_request_var('thold_fail_trigger');
|
|
|
|
// Time Based
|
|
$save['time_hi'] = trim_round_request_var('time_hi', 4, 'time_hi');
|
|
$save['time_low'] = trim_round_request_var('time_low', 4, 'time_low');
|
|
$save['time_fail_trigger'] = isempty_request_var('time_fail_trigger') ? read_config_option('thold_warning_time_fail_trigger') : get_nfilter_request_var('time_fail_trigger');
|
|
|
|
$save['time_fail_length'] = isempty_request_var('time_fail_length') ? (read_config_option('thold_warning_time_fail_length') > 0 ?
|
|
read_config_option('thold_warning_time_fail_length') : 1) : get_nfilter_request_var('time_fail_length');
|
|
|
|
// Warning High / Low
|
|
$save['thold_warning_hi'] = trim_round_request_var('thold_warning_hi', 4, 'thold_warning_hi');
|
|
$save['thold_warning_low'] = trim_round_request_var('thold_warning_low', 4, 'thold_warning_low');
|
|
$save['thold_warning_fail_trigger'] = isempty_request_var('thold_warning_fail_trigger') ? read_config_option('alert_trigger') : get_nfilter_request_var('thold_warning_fail_trigger');
|
|
|
|
// Warning Time Based
|
|
$save['time_warning_hi'] = trim_round_request_var('time_warning_hi', 4, 'time_warning_hi');
|
|
$save['time_warning_low'] = trim_round_request_var('time_warning_low', 4, 'time_warning_low');
|
|
$save['time_warning_fail_trigger'] = isempty_request_var('time_warning_fail_trigger') ?
|
|
read_config_option('thold_warning_time_fail_trigger') : get_nfilter_request_var('time_warning_fail_trigger');
|
|
|
|
$save['time_warning_fail_length'] = isempty_request_var('time_warning_fail_length') ?
|
|
(read_config_option('thold_warning_time_fail_length') > 0 ?
|
|
read_config_option('thold_warning_time_fail_length') : 1) : get_nfilter_request_var('time_warning_fail_length');
|
|
|
|
// Baseline
|
|
$save['bl_thold_valid'] = '0';
|
|
$save['bl_type'] = get_filter_request_var('bl_type');
|
|
$save['bl_cf'] = get_nfilter_request_var('bl_cf');
|
|
$save['bl_ref_time_range'] = isempty_request_var('bl_ref_time_range') ? read_config_option('alert_bl_timerange_def') : get_nfilter_request_var('bl_ref_time_range');
|
|
$save['bl_pct_down'] = trim_round_request_var('bl_pct_down', 4, 'bl_pct_down');
|
|
$save['bl_pct_up'] = trim_round_request_var('bl_pct_up', 4, 'bl_pct_up');
|
|
$save['bl_fail_trigger'] = isempty_request_var('bl_fail_trigger') ? read_config_option('alert_bl_trigger') : get_nfilter_request_var('bl_fail_trigger');
|
|
|
|
// Notification
|
|
$save['notify_extra'] = get_nfilter_request_var('notify_extra');
|
|
$save['notify_warning_extra'] = get_nfilter_request_var('notify_warning_extra');
|
|
$save['notify_warning'] = get_filter_request_var('notify_warning');
|
|
$save['notify_alert'] = get_filter_request_var('notify_alert');
|
|
|
|
// Notes
|
|
$save['notes'] = get_nfilter_request_var('notes');
|
|
$save['external_id'] = get_nfilter_request_var('external_id');
|
|
$save['format_file'] = get_nfilter_request_var('format_file');
|
|
$save['graph_timespan'] = get_nfilter_request_var('graph_timespan');
|
|
|
|
// Data Manipulation
|
|
$save['data_type'] = get_nfilter_request_var('data_type');
|
|
$save['percent_ds'] = (isset_request_var('percent_ds')) ? get_nfilter_request_var('percent_ds') : '';
|
|
$save['cdef'] = get_filter_request_var('cdef');
|
|
$save['expression'] = (isset_request_var('expression')) ? get_nfilter_request_var('expression') : '';
|
|
$save['upper_ds'] = (isset_request_var('upper_ds')) ? get_nfilter_request_var('upper_ds') : '';
|
|
$save['show_units'] = isset_request_var('show_units') && get_request_var('show_units') == 'on' ? 'on' : 'off';
|
|
$save['units_suffix'] = get_nfilter_request_var('units_suffix');
|
|
$save['decimals'] = get_nfilter_request_var('decimals');
|
|
|
|
// Email Subjects
|
|
$save['email_subject'] = get_nfilter_request_var('email_subject');
|
|
$save['email_subject_warn'] = get_nfilter_request_var('email_subject_warn');
|
|
$save['email_subject_restoral'] = get_nfilter_request_var('email_subject_restoral');
|
|
|
|
// Email Bodies
|
|
$save['email_body'] = get_nfilter_request_var('email_body');
|
|
$save['email_body_warn'] = get_nfilter_request_var('email_body_warn');
|
|
$save['email_body_restoral'] = get_nfilter_request_var('email_body_restoral');
|
|
|
|
// Command execution
|
|
$save['trigger_cmd_high'] = get_nfilter_request_var('trigger_cmd_high');
|
|
$save['trigger_cmd_low'] = get_nfilter_request_var('trigger_cmd_low');
|
|
$save['trigger_cmd_norm'] = get_nfilter_request_var('trigger_cmd_norm');
|
|
|
|
// SNMP Information
|
|
$save['snmp_event_category'] = get_filter_request_var('snmp_event_category');
|
|
$save['snmp_event_description'] = get_nfilter_request_var('snmp_event_description');
|
|
$save['snmp_event_severity'] = isset_request_var('snmp_event_severity') ? get_nfilter_request_var('snmp_event_severity') : 4;
|
|
$save['snmp_event_warning_severity'] = isset_request_var('snmp_event_warning_severity') ? get_nfilter_request_var('snmp_event_warning_severity') : 3;
|
|
|
|
if ($local_graph_id > 0 && $graph_template_id > 0) {
|
|
$save['local_graph_id'] = $local_graph_id;
|
|
$save['graph_template_id'] = $graph_template_id;
|
|
} elseif ($local_graph_id > 0) {
|
|
$save['local_graph_id'] = $local_graph_id;
|
|
$save['graph_template_id'] = $graph_template_id;
|
|
} else {
|
|
$grapharr = db_fetch_row_prepared('SELECT DISTINCT local_graph_id, graph_template_id
|
|
FROM graph_templates_item
|
|
WHERE task_item_id = ?',
|
|
[$save['data_template_rrd_id']]);
|
|
|
|
if ($grapharr === false || count($grapharr) == 0) {
|
|
thold_raise_message(__('Failed to find linked Graph Template Item \'%d\' on Threshold \'%d\'', $save['data_template_rrd_id'], $save['id'], 'thold'), MESSAGE_LEVEL_ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
$save['local_graph_id'] = $grapharr['local_graph_id'];
|
|
$save['graph_template_id'] = $grapharr['graph_template_id'];
|
|
}
|
|
|
|
if ($save['id'] > 0 && $save['local_graph_id'] > 0 && !is_thold_allowed_graph($save['local_graph_id'])) {
|
|
thold_raise_message(__('Permission Denied', 'thold'), MESSAGE_LEVEL_ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
if (isset_request_var('name') && get_nfilter_request_var('name') != '') {
|
|
$name = get_nfilter_request_var('name');
|
|
} else {
|
|
$name = '|data_source_description| [|data_source_name|]';
|
|
}
|
|
|
|
$name_cache = thold_expand_string($save, $name);
|
|
|
|
$save['name'] = $name;
|
|
$save['name_cache'] = $name_cache;
|
|
|
|
$save = api_plugin_hook_function('thold_edit_save_thold', $save);
|
|
|
|
if (!thold_validate_save($save, 'thold')) {
|
|
header('Location: thold.php?action=edit&header=false&id=' . ($save['id'] > 0 ? $save['id'] : ''));
|
|
exit;
|
|
}
|
|
|
|
$id = sql_save($save , 'thold_data');
|
|
|
|
if (isempty_request_var('id')) {
|
|
set_config_option('time_last_change_thold', time());
|
|
}
|
|
|
|
if (isset_request_var('notify_accounts') && is_array(get_nfilter_request_var('notify_accounts'))) {
|
|
thold_save_threshold_contacts($id, get_nfilter_request_var('notify_accounts'));
|
|
} elseif (!isset_request_var('notify_accounts')) {
|
|
thold_save_threshold_contacts($id, []);
|
|
}
|
|
|
|
if ($id) {
|
|
if ($thold_template_id > 0 && $save['template_enabled'] == 'on') {
|
|
thold_template_update_threshold($id, $thold_template_id);
|
|
}
|
|
|
|
plugin_thold_log_changes($id, 'modified', $save);
|
|
|
|
$thold_sql = "SELECT
|
|
td.*, dtd.rrd_step, tt.name AS template_name,
|
|
dtr.data_source_name as data_source, h.hostname,
|
|
h.description, h.notes AS dnotes, h.snmp_engine_id,
|
|
IF(IFNULL(td.`lastread`,'')='',NULL,(td.`lastread` + 0.0)) as `flastread`, td.`lasttime`,
|
|
IF(IFNULL(td.`oldvalue`,'')='',NULL,(td.`oldvalue` + 0.0)) as `foldvalue`, td.`repeat_alert`,
|
|
UNIX_TIMESTAMP() - UNIX_TIMESTAMP(lastchanged) AS `instate`
|
|
FROM thold_data AS td
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id = td.local_graph_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id = gl.graph_template_id
|
|
LEFT JOIN host AS h
|
|
ON h.id = gl.host_id
|
|
LEFT JOIN thold_template AS tt
|
|
ON tt.id = td.thold_template_id
|
|
LEFT JOIN data_template_data AS dtd
|
|
ON dtd.local_data_id = td.local_data_id
|
|
LEFT JOIN data_template_rrd AS dtr
|
|
ON dtr.id = td.data_template_rrd_id
|
|
WHERE td.id = ?";
|
|
|
|
$thold = db_fetch_row_prepared($thold_sql, [$id]);
|
|
|
|
if ($save['thold_type'] == 1) {
|
|
thold_check_threshold($thold);
|
|
}
|
|
|
|
set_request_var('id', $id);
|
|
} else {
|
|
set_request_var('id', '0');
|
|
}
|
|
|
|
if ($save['id'] == 0) {
|
|
$banner = __esc('Created Threshold: %s', $save['name_cache'], 'thold');
|
|
} else {
|
|
$banner = __('Record Updated', 'thold');
|
|
}
|
|
|
|
thold_raise_message($banner, MESSAGE_LEVEL_INFO);
|
|
|
|
return $id;
|
|
}
|
|
|
|
function trim_round_request_var($variable, $digits = 0, $field_name = '') {
|
|
$variable = trim(get_nfilter_request_var($variable));
|
|
|
|
if (!empty($variable)) {
|
|
$variable = thold_display_to_raw($variable, $field_name);
|
|
}
|
|
|
|
if ($variable == '0') {
|
|
return '0';
|
|
}
|
|
|
|
if (empty($variable)) {
|
|
return '';
|
|
}
|
|
|
|
if ($digits > 0) {
|
|
return round($variable, $digits);
|
|
} else {
|
|
return $variable;
|
|
}
|
|
}
|
|
|
|
function thold_save_template_contacts($id, $contacts) {
|
|
db_execute_prepared('DELETE
|
|
FROM plugin_thold_template_contact
|
|
WHERE template_id = ?',
|
|
[$id]);
|
|
|
|
if (!empty($contacts)) {
|
|
foreach ($contacts as $contact) {
|
|
db_execute_prepared('INSERT INTO plugin_thold_template_contact
|
|
(template_id, contact_id)
|
|
VALUES (?, ?)',
|
|
[$id, $contact]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_raise_message($message, $level = MESSAGE_LEVEL_NONE) {
|
|
static $thold_message_count = 0;
|
|
$message_id = 'thold_message_' . $thold_message_count;
|
|
|
|
cacti_log("raise_message($message_id, $message, $level);" . cacti_debug_backtrace('', false, false), false, 'THOLD', POLLER_VERBOSITY_DEBUG);
|
|
|
|
raise_message($message_id, $message, $level);
|
|
$thold_message_count++;
|
|
}
|
|
|
|
function thold_save_threshold_contacts($id, $contacts) {
|
|
db_execute_prepared('DELETE
|
|
FROM plugin_thold_threshold_contact
|
|
WHERE thold_id = ?',
|
|
[$id]);
|
|
|
|
foreach ($contacts as $contact) {
|
|
db_execute_prepared('INSERT INTO plugin_thold_threshold_contact
|
|
(thold_id, contact_id)
|
|
VALUES (?, ?)',
|
|
[$id, $contact]);
|
|
}
|
|
}
|
|
|
|
function thold_validate_save($save, $type = 'thold_template') {
|
|
/**
|
|
* Type Types:
|
|
* 0 - Hi / Low
|
|
* 1 - Baseline Deviation
|
|
* 2 - Time Based
|
|
*/
|
|
$banner = '';
|
|
|
|
/**
|
|
* Only validate thresholds once they are created
|
|
* This is required due to the wizard control on the
|
|
* Thold page.
|
|
*/
|
|
if ($type == 'thold' && empty($save['id'])) {
|
|
return true;
|
|
}
|
|
|
|
if ($save['thold_type'] == 0) {
|
|
/**
|
|
* Hi / Low Checks
|
|
*
|
|
* Alert must always be set except when first creating a thold!
|
|
*/
|
|
if (isset($save['thold_hi'])) {
|
|
if ($save['thold_hi'] == '' && $save['thold_low'] == '') {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('You must specify either \'High Alert Threshold\' or \'Low Alert Threshold\' or both!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['thold_hi'] = 'thold_hi';
|
|
$_SESSION['sess_error_fields']['thold_low'] = 'thold_low';
|
|
}
|
|
|
|
if ($save['thold_hi'] != '' && $save['thold_low'] != '' && $save['thold_low'] >= $save['thold_hi']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'High Alert Threshold\' smaller than the \'Low Alert Threshold\'!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['thold_hi'] = 'thold_hi';
|
|
$_SESSION['sess_error_fields']['thold_low'] = 'thold_low';
|
|
}
|
|
|
|
// Warning is optional. Check if set!
|
|
if ($save['thold_warning_hi'] != '' || $save['thold_warning_low'] != '') {
|
|
if ($save['thold_warning_hi'] != '' && $save['thold_warning_low'] != '' && $save['thold_warning_low'] >= $save['thold_warning_hi']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'High Warning Threshold\' smaller than the \'Low Warning Threshold\'!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['thold_warning_hi'] = 'thold_warning_hi';
|
|
$_SESSION['sess_error_fields']['thold_warning_low'] = 'thold_warning_low';
|
|
}
|
|
|
|
if (!empty($save['thold_warning_hi']) && $save['thold_hi'] <= $save['thold_warning_hi']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'High Warning Threshold\' larger than the \'High Alert Threshold\'!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['thold_hi'] = 'thold_hi';
|
|
$_SESSION['sess_error_fields']['thold_warning_hi'] = 'thold_warning_hi';
|
|
}
|
|
|
|
if (!empty($save['thold_warning_low']) && $save['thold_low'] >= $save['thold_warning_low']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'Low Alert Threshold\' larger than the \'Low Warning Threshold\'!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['thold_low'] = 'thold_low';
|
|
$_SESSION['sess_error_fields']['thold_warning_low'] = 'thold_warning_low';
|
|
}
|
|
}
|
|
}
|
|
} elseif ($save['thold_type'] == 1) {
|
|
/**
|
|
* Baseline Deviation Checks
|
|
*
|
|
* The initial template creation is always hi/low. So, we
|
|
* do not require an isset in this section.
|
|
*/
|
|
|
|
if (empty($save['bl_ref_time_range']) || $save['bl_ref_time_range'] <= 0) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Time reference in the past must be set to positive integer value!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['bl_ref_time_range'] = 'bl_ref_time_range';
|
|
}
|
|
|
|
if (empty($save['bl_pct_down']) && empty($save['bl_pct_up'])) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('You must specify either \'Baseline Deviation UP\' or \'Baseline Deviation DOWN\' or both!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['bl_pct_up'] = 'bl_pct_up';
|
|
$_SESSION['sess_error_fields']['bl_pct_down'] = 'bl_pct_down';
|
|
}
|
|
} elseif ($save['thold_type'] == 2) {
|
|
/**
|
|
* Time Based Checks
|
|
*
|
|
* The initial template creation is always hi/low. So, we
|
|
* do not require an isset in this section.
|
|
*/
|
|
if ($save['time_hi'] == '' && $save['time_low'] == '') {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('You must specify either \'High Alert Threshold\' or \'Low Alert Threshold\' or both!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_hi'] = 'time_hi';
|
|
$_SESSION['sess_error_fields']['time_low'] = 'time_low';
|
|
}
|
|
|
|
if ($save['time_hi'] != '' && $save['time_low'] != '' && $save['time_low'] >= $save['time_hi']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'High Alert Threshold\' smaller than the \'Low Alert Threshold\'', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_hi'] = 'time_hi';
|
|
$_SESSION['sess_error_fields']['time_low'] = 'time_low';
|
|
}
|
|
|
|
if (empty($save['time_fail_trigger']) || $save['time_fail_trigger'] <= 0) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: The Alert Trigger Count must be greater or eval to 1!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_fail_trigger'] = 'time_fail_trigger';
|
|
}
|
|
|
|
if ($save['time_fail_length'] < $save['time_fail_trigger']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: The Alert Trigger Count must be less than or equal to the Trigger Count or eval to 1!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_fail_length'] = 'time_fail_length';
|
|
$_SESSION['sess_error_fields']['time_fail_trigger'] = 'time_fail_trigger';
|
|
}
|
|
|
|
// Warning is optional. Check if set!
|
|
if ($save['time_warning_hi'] != '' || $save['time_warning_low'] != '') {
|
|
if ($save['time_warning_hi'] != '' && $save['time_warning_low'] != '' && $save['time_warning_low'] >= $save['time_warning_hi']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'High Warning Threshold\' smaller than the \'Low Warning Threshold\'!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_warning_hi'] = 'time_warning_hi';
|
|
$_SESSION['sess_error_fields']['time_warning_low'] = 'time_warning_low';
|
|
}
|
|
|
|
if (empty($save['time_warning_fail_trigger']) || $save['time_warning_fail_trigger'] <= 0) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: The Warning Trigger Count must be greater or eval to 1!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_warning_fail_trigger'] = 'time_warning_fail_trigger';
|
|
}
|
|
|
|
if ($save['time_warning_fail_length'] < $save['time_warning_fail_trigger']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: The Warning Trigger Count must be less than or equal to the Trigger Count or eval to 1!', 'thold');
|
|
$_SESSION['sess_error_fields']['time_warning_fail_trigger'] = 'time_warning_fail_trigger';
|
|
$_SESSION['sess_error_fields']['time_warning_fail_length'] = 'time_warning_fail_length';
|
|
}
|
|
|
|
if (!empty($save['time_warning_hi']) && $save['time_hi'] <= $save['time_warning_hi']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'High Warning Threshold\' larger than the \'High Alert Threshold\'!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_hi'] = 'time_hi';
|
|
$_SESSION['sess_error_fields']['time_warning_hi'] = 'time_warning_hi';
|
|
}
|
|
|
|
if (!empty($save['time_warning_low']) && $save['time_low'] >= $save['time_warning_low']) {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Impossible threshold: \'Low Warning Threshold\' smaller than the \'Low Alert Threshold\'!', 'thold');
|
|
|
|
$_SESSION['sess_error_fields']['time_low'] = 'time_low';
|
|
$_SESSION['sess_error_fields']['time_warning_low'] = 'time_warning_low';
|
|
}
|
|
}
|
|
} else {
|
|
$banner .= ($banner != '' ? '<br>' : '') . __('Unknown Threshold Type!', 'thold');
|
|
}
|
|
|
|
if ($banner != '') {
|
|
thold_raise_message($banner, MESSAGE_LEVEL_ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// populate the save structure from a thold template
|
|
function thold_create_thold_save_from_template($save, $template) {
|
|
// General Settings
|
|
$save['name'] = $template['suggested_name'];
|
|
$save['data_template_id'] = $template['data_template_id'];
|
|
$save['data_source_name'] = $template['data_source_name'];
|
|
$save['thold_template_id'] = $template['id'];
|
|
$save['template_enabled'] = 'on';
|
|
$save['thold_enabled'] = $template['thold_enabled'];
|
|
$save['thold_type'] = $template['thold_type'];
|
|
|
|
// Additional General
|
|
$save['thold_alert'] = 0;
|
|
$save['restored_alert'] = $template['restored_alert'];
|
|
$save['repeat_alert'] = $template['repeat_alert'];
|
|
$save['exempt'] = $template['exempt'];
|
|
|
|
// Alert High/Low
|
|
$save['thold_hi'] = $template['thold_hi'];
|
|
$save['thold_low'] = $template['thold_low'];
|
|
$save['thold_fail_trigger'] = $template['thold_fail_trigger'];
|
|
|
|
// Warning High/Low
|
|
$save['thold_warning_hi'] = $template['thold_warning_hi'];
|
|
$save['thold_warning_low'] = $template['thold_warning_low'];
|
|
$save['thold_warning_fail_trigger'] = $template['thold_warning_fail_trigger'];
|
|
$save['thold_warning_fail_count'] = $template['thold_warning_fail_count'];
|
|
|
|
// Alert Time Based
|
|
$save['time_hi'] = $template['time_hi'];
|
|
$save['time_low'] = $template['time_low'];
|
|
$save['time_fail_trigger'] = $template['time_fail_trigger'];
|
|
$save['time_fail_length'] = $template['time_fail_length'];
|
|
|
|
// Warning Time Based
|
|
$save['time_warning_hi'] = $template['time_warning_hi'];
|
|
$save['time_warning_low'] = $template['time_warning_low'];
|
|
$save['time_warning_fail_trigger'] = $template['time_warning_fail_trigger'];
|
|
$save['time_warning_fail_length'] = $template['time_warning_fail_length'];
|
|
|
|
// Baseline
|
|
$save['bl_type'] = $template['bl_type'];
|
|
$save['bl_cf'] = $template['bl_cf'];
|
|
$save['bl_ref_time_range'] = $template['bl_ref_time_range'];
|
|
$save['bl_pct_down'] = $template['bl_pct_down'];
|
|
$save['bl_pct_up'] = $template['bl_pct_up'];
|
|
$save['bl_fail_trigger'] = $template['bl_fail_trigger'];
|
|
$save['bl_fail_count'] = $template['bl_fail_count'];
|
|
$save['bl_alert'] = $template['bl_alert'];
|
|
|
|
// Notification
|
|
$save['notify_alert'] = $template['notify_alert'];
|
|
$save['notify_warning'] = $template['notify_warning'];
|
|
$save['notify_extra'] = $template['notify_extra'];
|
|
$save['notify_warning_extra'] = $template['notify_warning_extra'];
|
|
|
|
// Data Manipulation
|
|
$save['data_type'] = $template['data_type'];
|
|
$save['cdef'] = $template['cdef'];
|
|
$save['percent_ds'] = $template['percent_ds'];
|
|
$save['expression'] = $template['expression'];
|
|
$save['upper_ds'] = $template['upper_ds'];
|
|
$save['decimals'] = $template['decimals'];
|
|
$save['units_suffix'] = $template['units_suffix'];
|
|
$save['show_units'] = $template['show_units'];
|
|
|
|
// Hrules
|
|
$save['thold_hrule_alert'] = $template['thold_hrule_alert'];
|
|
$save['thold_hrule_warning'] = $template['thold_hrule_warning'];
|
|
$save['skipscale'] = $template['skipscale'];
|
|
|
|
// Syslog
|
|
$save['syslog_enabled'] = $template['syslog_enabled'];
|
|
$save['syslog_priority'] = $template['syslog_priority'];
|
|
$save['syslog_facility'] = $template['syslog_facility'];
|
|
|
|
// Command execution
|
|
$save['trigger_cmd_high'] = $template['trigger_cmd_high'];
|
|
$save['trigger_cmd_low'] = $template['trigger_cmd_low'];
|
|
$save['trigger_cmd_norm'] = $template['trigger_cmd_norm'];
|
|
|
|
// Acknowledgment
|
|
$save['reset_ack'] = $template['reset_ack'];
|
|
$save['persist_ack'] = $template['persist_ack'];
|
|
|
|
// Email Subjects
|
|
$save['email_subject'] = $template['email_subject'];
|
|
$save['email_subject_warn'] = $template['email_subject_warn'];
|
|
$save['email_subject_restoral'] = $template['email_subject_restoral'];
|
|
|
|
// Email Bodies
|
|
$save['email_body'] = $template['email_body'];
|
|
$save['email_body_warn'] = $template['email_body_warn'];
|
|
$save['email_body_restoral'] = $template['email_body_restoral'];
|
|
|
|
// SNMP
|
|
$save['snmp_event_category'] = $template['snmp_event_category'];
|
|
$save['snmp_event_description'] = $template['snmp_event_description'];
|
|
$save['snmp_event_severity'] = $template['snmp_event_severity'];
|
|
$save['snmp_event_warning_severity'] = $template['snmp_event_warning_severity'];
|
|
|
|
// Other
|
|
$save['notes'] = $template['notes'];
|
|
$save['external_id'] = $template['external_id'];
|
|
$save['format_file'] = $template['format_file'];
|
|
$save['graph_timespan'] = $template['graph_timespan'];
|
|
|
|
return $save;
|
|
}
|
|
|
|
// Create tholds for all possible data elements for a host
|
|
function autocreate($device_ids, $graph_ids = '', $graph_template_id = '', $thold_template_id = '', $log = false) {
|
|
$created = 0;
|
|
$message = '';
|
|
$device_id = 0;
|
|
|
|
// Don't autocreate if not asked to
|
|
if (isset_request_var('save_autocreate') && get_filter_request_var('save_autocreate') == 0) {
|
|
return;
|
|
}
|
|
|
|
$sql_where = '';
|
|
|
|
if (!empty($thold_template_id) && is_numeric($thold_template_id)) {
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'tt.id = ' . $thold_template_id;
|
|
|
|
if (empty($graph_template_id)) {
|
|
$data_template_id = db_fetch_cell_prepared('SELECT data_template_id
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$thold_template_id]);
|
|
|
|
if ($data_template_id > 0) {
|
|
$graph_template_ids = array_rekey(
|
|
db_fetch_assoc_prepared('SELECT DISTINCT gti.graph_template_id
|
|
FROM graph_templates_item AS gti
|
|
INNER JOIN data_template_rrd AS dtr
|
|
ON gti.task_item_id = dtr.id
|
|
AND gti.local_graph_id = 0
|
|
AND dtr.data_template_id = ?',
|
|
[$data_template_id]),
|
|
'graph_template_id', 'graph_template_id'
|
|
);
|
|
|
|
if (cacti_sizeof($graph_template_ids)) {
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'gl.graph_template_id IN (' . implode(', ', $graph_template_ids) . ')';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($graph_template_id) && is_numeric($graph_template_id)) {
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'gl.graph_template_id = ' . $graph_template_id;
|
|
}
|
|
|
|
if (is_array($graph_ids) && cacti_sizeof($graph_ids)) {
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'gti.local_graph_id IN(' . implode(', ', $graph_ids) . ')';
|
|
}
|
|
|
|
if (is_array($device_ids)) {
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'gl.host_id IN(' . implode($device_ids) . ')';
|
|
} elseif ($device_ids > 0) {
|
|
$device_id = $device_ids;
|
|
}
|
|
|
|
if ($device_id > 0) {
|
|
$host_template_id = db_fetch_cell_prepared('SELECT host_template_id
|
|
FROM host
|
|
WHERE id = ?',
|
|
[$device_id]);
|
|
|
|
$templates = db_fetch_assoc_prepared('SELECT tt.*
|
|
FROM thold_template AS tt
|
|
INNER JOIN plugin_thold_host AS pth
|
|
ON tt.id = pth.thold_template_id
|
|
WHERE pth.host_id = ?',
|
|
[$device_id]);
|
|
|
|
if (!cacti_sizeof($templates)) {
|
|
if ($log) {
|
|
thold_raise_message(__('No Thresholds Templates associated with the Device\'s Template.', 'thold'), MESSAGE_LEVEL_ERROR);
|
|
}
|
|
|
|
return 0;
|
|
} else {
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'gl.host_id = ' . $device_id;
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'dtr.data_source_name = ?';
|
|
|
|
foreach ($templates as $template) {
|
|
$new_where = $sql_where . ' AND tt.id = ' . $template['id'];
|
|
|
|
$data_sources = db_fetch_assoc_prepared("SELECT DISTINCT
|
|
dtr.id, gti.local_graph_id, local_data_id, gl.snmp_query_id
|
|
FROM data_template_rrd AS dtr
|
|
INNER JOIN thold_template AS tt
|
|
ON tt.data_template_id = dtr.data_template_id
|
|
AND tt.data_source_name = dtr.data_source_name
|
|
INNER JOIN graph_templates_item AS gti
|
|
ON gti.task_item_id = dtr.id
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id = gti.local_graph_id
|
|
$new_where",
|
|
[$template['data_source_name']]);
|
|
|
|
if (cacti_sizeof($data_sources)) {
|
|
foreach ($data_sources as $data_source) {
|
|
$local_data_id = $data_source['local_data_id'];
|
|
$local_graph_id = $data_source['local_graph_id'];
|
|
$data_template_rrd_id = $data_source['id'];
|
|
|
|
// Don't create a second threshold for a data source that already has a threshold
|
|
if ($data_source['snmp_query_id'] > 0) {
|
|
$exists = db_fetch_cell_prepared('SELECT id
|
|
FROM thold_data
|
|
WHERE local_data_id = ?
|
|
AND thold_template_id = ?
|
|
AND data_template_rrd_id = ?',
|
|
[$local_data_id, $template['id'], $data_template_rrd_id]);
|
|
} else {
|
|
$exists = false;
|
|
}
|
|
|
|
if (!$exists && thold_create_from_template($local_data_id, $local_graph_id, $data_template_rrd_id, $template, $message)) {
|
|
$created++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$data_sources = db_fetch_assoc("SELECT DISTINCT
|
|
dtr.id, gl.id AS local_graph_id, local_data_id, tt.id AS thold_template_id, gl.snmp_query_id
|
|
FROM data_template_rrd AS dtr
|
|
INNER JOIN thold_template AS tt
|
|
ON tt.data_template_id = dtr.data_template_id
|
|
AND tt.data_source_name = dtr.data_source_name
|
|
INNER JOIN graph_templates_item AS gti
|
|
ON gti.task_item_id = dtr.id
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id = gti.local_graph_id
|
|
$sql_where");
|
|
|
|
if (cacti_sizeof($data_sources)) {
|
|
foreach ($data_sources as $data_source) {
|
|
$local_data_id = $data_source['local_data_id'];
|
|
$local_graph_id = $data_source['local_graph_id'];
|
|
$data_template_rrd_id = $data_source['id'];
|
|
|
|
$template = db_fetch_row_prepared('SELECT *
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$data_source['thold_template_id']]);
|
|
|
|
if (cacti_sizeof($template)) {
|
|
foreach ($data_sources as $data_source) {
|
|
// Don't create a second threshold for a data source that already has a threshold
|
|
if ($data_source['snmp_query_id'] > 0) {
|
|
$exists = db_fetch_cell_prepared('SELECT id
|
|
FROM thold_data
|
|
WHERE local_data_id = ?
|
|
AND thold_template_id = ?
|
|
AND data_template_rrd_id = ?',
|
|
[$local_data_id, $template['id'], $data_template_rrd_id]);
|
|
} else {
|
|
$exists = false;
|
|
}
|
|
|
|
if (!$exists && thold_create_from_template($local_data_id, $local_graph_id, $data_template_rrd_id, $template, $message)) {
|
|
$created++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strlen($message)) {
|
|
thold_raise_message($message, MESSAGE_LEVEL_INFO);
|
|
} else {
|
|
thold_raise_message(__('No Threshold(s) Created. Either they already exist, or no suitable matches found.', 'thold'), MESSAGE_LEVEL_INFO);
|
|
}
|
|
|
|
return $created;
|
|
}
|
|
|
|
function thold_create_from_template($local_data_id, $local_graph_id, $data_template_rrd_id, $template_or_id, &$message) {
|
|
if (is_array($template_or_id)) {
|
|
$template = $template_or_id;
|
|
} else {
|
|
$template = db_fetch_row_prepared('SELECT *
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$template_or_id]);
|
|
}
|
|
|
|
$data_source_name = db_fetch_cell_prepared('SELECT data_source_name
|
|
FROM data_template_rrd
|
|
WHERE id = ?',
|
|
[$data_template_rrd_id]);
|
|
|
|
// Don't create the threshold if the dtr data source
|
|
// does not match the templates
|
|
if ($data_source_name != $template['data_source_name']) {
|
|
return false;
|
|
}
|
|
|
|
$exists = db_fetch_cell_prepared('SELECT id
|
|
FROM thold_data
|
|
WHERE local_graph_id = ?
|
|
AND local_data_id = ?
|
|
AND data_template_rrd_id = ?
|
|
AND data_source_name = ?
|
|
AND thold_template_id = ?',
|
|
[
|
|
$local_graph_id,
|
|
$local_data_id,
|
|
$data_template_rrd_id,
|
|
$template['data_source_name'],
|
|
$template['id']
|
|
]
|
|
);
|
|
|
|
if (!$exists) {
|
|
$graph = db_fetch_row_prepared('SELECT gtg.local_graph_id, gtg.title_cache,
|
|
gtg.graph_template_id, gl.host_id
|
|
FROM graph_templates_graph AS gtg
|
|
INNER JOIN graph_local AS gl
|
|
ON gl.id = gtg.local_graph_id
|
|
WHERE gtg.local_graph_id = ?',
|
|
[$local_graph_id]);
|
|
|
|
if (cacti_sizeof($template) && cacti_sizeof($graph)) {
|
|
$save = [];
|
|
$save['id'] = 0;
|
|
$save['local_data_id'] = $local_data_id;
|
|
$save['data_template_rrd_id'] = $data_template_rrd_id;
|
|
$save['local_graph_id'] = $graph['local_graph_id'];
|
|
$save['graph_template_id'] = $graph['graph_template_id'];
|
|
$save['host_id'] = $graph['host_id'];
|
|
|
|
$save = thold_create_thold_save_from_template($save, $template);
|
|
|
|
$save['name_cache'] = thold_expand_string($save, $save['name']);
|
|
|
|
$save = api_plugin_hook_function('thold_edit_save_thold', $save);
|
|
|
|
if (!thold_validate_save($save, 'thold')) {
|
|
header('Location: thold.php?action=edit&header=false&id=' . ($save['id'] > 0 ? $save['id'] : ''));
|
|
exit;
|
|
}
|
|
|
|
$id = sql_save($save, 'thold_data');
|
|
|
|
set_config_option('time_last_change_thold', time());
|
|
|
|
if ($id) {
|
|
thold_template_update_threshold($id, $save['thold_template_id']);
|
|
plugin_thold_log_changes($id, 'auto_created', $save['name_cache']);
|
|
|
|
$message .= __esc('Created Threshold: %s', $save['name_cache'], 'thold') . '<br>';
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Sends a group of graphs to a user
|
|
function thold_mail($to_email, $bcc_email, $from_email, $subject, $message, $filename, $headers = [], $notify_list_id = 0, &$host = [], $format_file = '', $graph_timespan = 7, $topic = 'thold_mail') {
|
|
thold_debug('Preparing to send email');
|
|
global $config;
|
|
|
|
$subject = trim($subject);
|
|
$message = thold_str_replace('<SUBJECT>', $subject, $message);
|
|
|
|
if ($from_email == '') {
|
|
$from_email = read_config_option('thold_from_email');
|
|
$from_name = read_config_option('thold_from_name');
|
|
|
|
if ($from_email == '') {
|
|
if (isset($_SERVER['HOSTNAME'])) {
|
|
$from_email = 'cacti@' . $_SERVER['HOSTNAME'];
|
|
} else {
|
|
$from_email = 'cacti@' . gethostname();
|
|
}
|
|
}
|
|
|
|
if ($from_name == '') {
|
|
$from_name = 'Cacti';
|
|
}
|
|
}
|
|
|
|
if ($to_email == '') {
|
|
return __('Mailer Error: No <b>TO</b> address set!!<br>If using the <i>Test Mail</i> link, please set the <b>Alert Email</b> setting.', 'thold');
|
|
}
|
|
|
|
$attachments = [];
|
|
|
|
$notification_queue = read_config_option('thold_notification_queue');
|
|
|
|
if (is_array($filename) && sizeof($filename) && strstr($message, '<GRAPH>') !== 0) {
|
|
if (isset($filename['local_data_id'])) {
|
|
$tmp = [];
|
|
$tmp[] = $filename;
|
|
$filename = $tmp;
|
|
}
|
|
|
|
$time = time();
|
|
|
|
// get config option for first-day-of-the-week
|
|
$first_weekdayid = read_user_setting('first_weekdayid');
|
|
|
|
$timespan = [];
|
|
|
|
// get start/end time-since-epoch for actual time (now()) and given current-session-timespan
|
|
get_timespan($timespan, $time, $graph_timespan, $first_weekdayid);
|
|
|
|
foreach ($filename as $val) {
|
|
$graph_data_array = [
|
|
'graph_start' => $timespan['begin_now'],
|
|
'graph_end' => $timespan['end_now'],
|
|
'image_format' => 'png',
|
|
'graph_theme' => 'modern',
|
|
'output_flag' => RRDTOOL_OUTPUT_STDOUT,
|
|
'disable_cache' => true
|
|
];
|
|
|
|
if ($notification_queue == 'on') {
|
|
$attach = base64_encode(rrdtool_function_graph($val['local_graph_id'], '', $graph_data_array, ''));
|
|
} else {
|
|
$attach = rrdtool_function_graph($val['local_graph_id'], '', $graph_data_array, '');
|
|
}
|
|
|
|
$attachments[] = [
|
|
'attachment' => $attach,
|
|
'filename' => 'graph_' . $val['local_graph_id'] . '.png',
|
|
'mime_type' => 'image/png',
|
|
'local_graph_id' => $val['local_graph_id'],
|
|
'local_data_id' => $val['local_data_id'],
|
|
'inline' => 'inline'
|
|
];
|
|
}
|
|
}
|
|
|
|
$text = ['text' => '', 'html' => ''];
|
|
|
|
if (empty($filename)) {
|
|
$text['html'] = $message . '<br>';
|
|
|
|
$message = str_replace('<br>', "\n", $message);
|
|
$message = str_replace('<BR>', "\n", $message);
|
|
$message = str_replace('</BR>', "\n", $message);
|
|
$text['text'] = strip_tags(str_replace('<br>', "\n", $message));
|
|
} else {
|
|
$text['html'] = $message . '<br>';
|
|
$text['text'] = strip_tags(str_replace('<br>', "\n", $message));
|
|
}
|
|
|
|
$format_data = '';
|
|
$report_tag = false;
|
|
$format_ok = false;
|
|
$theme = read_config_option('selected_theme');
|
|
|
|
if ($theme == '') {
|
|
$theme = 'classic';
|
|
}
|
|
|
|
// process the format file as applicable
|
|
if ($format_file != '') {
|
|
include_once($config['library_path'] . '/reports.php');
|
|
$format_ok = reports_load_format_file($format_file, $format_data, $report_tag, $theme);
|
|
}
|
|
|
|
if (($format_ok && $report_tag) || strpos($text['html'], '<body>') !== false) {
|
|
$include_body = false;
|
|
} else {
|
|
$include_body = true;
|
|
}
|
|
|
|
if ($include_body) {
|
|
$text['html'] = '<body>' . $text['html'] . '</body>';
|
|
}
|
|
|
|
if ($format_ok) {
|
|
if ($report_tag) {
|
|
$text['html'] = str_replace('<REPORT>', $text['html'], $format_data);
|
|
} else {
|
|
$text['html'] = $format_data . PHP_EOL . $text['html'];
|
|
}
|
|
}
|
|
|
|
$version = db_fetch_cell("SELECT version
|
|
FROM plugin_config
|
|
WHERE directory='thold'");
|
|
|
|
if (!is_array($headers)) {
|
|
$headers = [];
|
|
}
|
|
|
|
$headers['X-Mailer'] = 'Cacti-Thold-v' . $version;
|
|
$headers['User-Agent'] = 'Cacti-Thold-v' . $version;
|
|
|
|
if (read_config_option('thold_email_prio') == 'on') {
|
|
$headers['X-Priority'] = '1';
|
|
}
|
|
|
|
thold_debug("Queuing email to '" . trim($to_email,', ') . "'");
|
|
|
|
$thold_send_text_only = read_config_option('thold_send_text_only');
|
|
$thold_send_email_separately = read_config_option('thold_send_email_separately');
|
|
|
|
$any_error = '';
|
|
|
|
if ($thold_send_email_separately != 'on') {
|
|
if ($notification_queue == 'on') {
|
|
$data = [
|
|
'from' => [$from_email, $from_name],
|
|
'to' => $to_email,
|
|
'bcc' => $bcc_email,
|
|
'subject' => $subject,
|
|
'body' => $text['html'],
|
|
'body_text' => $text['text'],
|
|
'attachments' => empty($attachments) ? null : $attachments,
|
|
'headers' => $headers,
|
|
'html' => $thold_send_text_only != 'on',
|
|
'id' => (isset($host['thold_id']) ? $host['thold_id'] : $host['id'])
|
|
];
|
|
|
|
thold_notification_add($topic, $data, 'id', $notify_list_id, $host);
|
|
} else {
|
|
$any_error = mailer(
|
|
[$from_email, $from_name],
|
|
$to_email,
|
|
'',
|
|
$bcc_email,
|
|
'',
|
|
$subject,
|
|
$text['html'],
|
|
$text['text'],
|
|
empty($attachments) ? null : $attachments,
|
|
$headers,
|
|
$thold_send_text_only != 'on'
|
|
);
|
|
}
|
|
} else {
|
|
$ar_to_email = explode(',', $to_email);
|
|
|
|
foreach ($ar_to_email as $to) {
|
|
if (filter_var($to, FILTER_VALIDATE_EMAIL) == $to) {
|
|
if ($notification_queue == 'on') {
|
|
$data = [
|
|
'from' => [$from_email, $from_name],
|
|
'to' => $to,
|
|
'bcc' => $bcc_email,
|
|
'subject' => $subject,
|
|
'body' => $text['html'],
|
|
'body_text' => $text['text'],
|
|
'attachments' => empty($attachments) ? '' : $attachments,
|
|
'headers' => $headers,
|
|
'html' => $thold_send_text_only != 'on',
|
|
'id' => (isset($host['thold_id']) ? $host['thold_id'] : $host['id'])
|
|
];
|
|
|
|
thold_notification_add($topic, $data, 'id', $notify_list_id, $host);
|
|
} else {
|
|
$error = mailer(
|
|
[$from_email, $from_name],
|
|
$to,
|
|
'',
|
|
'',
|
|
'',
|
|
$subject,
|
|
$text['html'],
|
|
$text['text'],
|
|
empty($attachments) ? '' : $attachments,
|
|
$headers,
|
|
$thold_send_text_only != 'on'
|
|
);
|
|
|
|
if ($error != '') {
|
|
cacti_log("ERROR: Sending Email Failed To:$to Subject:$subject. Error was:'$error'", true, 'THOLD');
|
|
|
|
$any_error = $error;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($any_error != '') {
|
|
return $any_error;
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
function thold_notification_add($topic, &$data, $id = 'id', $list_id = 0, &$host = []) {
|
|
$now = date('Y-m-d H:i:s');
|
|
|
|
if (isset($data['data'][$id])) {
|
|
$id = $data['data'][$id];
|
|
} else {
|
|
$id = 0;
|
|
}
|
|
|
|
if (isset($data['data']['name'])) {
|
|
$name = $data['data']['name'];
|
|
} elseif (isset($data['data']['description'])) {
|
|
$name = $data['data']['description'];
|
|
} elseif (isset($data['subject'])) {
|
|
$name = $data['subject'];
|
|
} else {
|
|
$name = 'Not Specfified';
|
|
}
|
|
|
|
if (isset($host['id'])) {
|
|
$host_id = $host['id'];
|
|
} else {
|
|
$host_id = 0;
|
|
}
|
|
|
|
if (isset($host['hostname'])) {
|
|
if ($host['hostname'] == 'localhost') {
|
|
$hostname = $host['description'];
|
|
} else {
|
|
$hostname = $host['hostname'];
|
|
}
|
|
} else {
|
|
$hostname = 'unknown';
|
|
}
|
|
|
|
db_execute_prepared('INSERT INTO notification_queue
|
|
(topic, notification_list_id, object_id, object_name, host_id, hostname, event_time, event_data) VALUES
|
|
(?, ?, ?, ?, ?, ?, ?, ?)',
|
|
[$topic, $list_id, $id, $name, $host_id, $hostname, $now, json_encode($data, JSON_PRETTY_PRINT)]);
|
|
}
|
|
|
|
function pre_process_device_notifications() {
|
|
$delay_criteria = read_config_option('alert_notification_pause');
|
|
$now = time();
|
|
$triggers = [];
|
|
$last_check = read_config_option('alert_deadnotify_last_check');
|
|
$last_trigger = read_config_option('alert_deadnotify_state');
|
|
|
|
if ($last_trigger != '') {
|
|
$last_trigger = json_decode($last_trigger, true);
|
|
}
|
|
|
|
if ($delay_criteria != '') {
|
|
$options = explode(',', $delay_criteria);
|
|
|
|
foreach ($options as $option) {
|
|
$value_array = explode('|', $option);
|
|
|
|
if (isset($value_array[0])) {
|
|
$value = $value_array[0];
|
|
} else {
|
|
$value = '';
|
|
}
|
|
|
|
if (isset($value_array[1])) {
|
|
$type = $value_array[1];
|
|
} else {
|
|
$type = '';
|
|
}
|
|
|
|
switch($type) {
|
|
case 'eg': // Global events
|
|
$events = db_fetch_cell_prepared('SELECT COUNT(*) AS events
|
|
FROM notification_queue
|
|
WHERE event_processed = 0
|
|
AND topic IN ("thold_dhost_mail", "thold_dhost_cmd")
|
|
AND event_time BETWEEN ? AND ?',
|
|
[
|
|
date('Y-m-d H:i:s', $last_check),
|
|
date('Y-m-d H:i:s', $now)
|
|
]
|
|
);
|
|
|
|
if ($events > $value) {
|
|
$triggers[$option] = [
|
|
'events' => $events,
|
|
'time' => $now
|
|
];
|
|
}
|
|
|
|
break;
|
|
case 'es': // Events per Site
|
|
$events = db_fetch_assoc_prepared('SELECT site_id, COUNT(*) AS events
|
|
FROM notification_queue AS nq
|
|
INNER JOIN host AS h
|
|
ON nq.host_id = h.id
|
|
WHERE event_processed = 0
|
|
AND topic IN ("thold_dhost_mail", "thold_dhost_cmd")
|
|
AND event_time BETWEEN ? AND ?
|
|
GROUP BY site_id
|
|
HAVING events > ?',
|
|
[
|
|
date('Y-m-d H:i:s', $last_check),
|
|
date('Y-m-d H:i:s', $now),
|
|
$value
|
|
]
|
|
);
|
|
|
|
if (cacti_sizeof($events)) {
|
|
foreach ($events as $e) {
|
|
$triggers[$option . '|' . $e['site_id']] = [
|
|
'events' => $e['events'],
|
|
'time' => $now
|
|
];
|
|
}
|
|
}
|
|
|
|
break;
|
|
case 'es': // Percent of events per Site
|
|
$events = db_fetch_assoc_prepared('SELECT h.site_id, COUNT(*) AS events, th.total_hosts
|
|
FROM notification_queue AS nq
|
|
INNER JOIN host AS h
|
|
ON nq.host_id = h.id
|
|
INNER JOIN (
|
|
SELECT site_id, COUNT(*) AS total_hosts
|
|
FROM host
|
|
WHERE disabled = ""
|
|
AND deleted = ""
|
|
GROUP BY site_id
|
|
) AS th
|
|
ON th.site_id = h.site_id
|
|
WHERE nq.event_processed = 0
|
|
AND nq.topic IN ("thold_dhost_mail", "thold_dhost_cmd")
|
|
AND nq.event_time BETWEEN ? AND ?
|
|
GROUP BY h.site_id
|
|
HAVING (events / total_hosts) * 100 > ?',
|
|
[
|
|
date('Y-m-d H:i:s', $last_check),
|
|
date('Y-m-d H:i:s', $now),
|
|
$value
|
|
]
|
|
);
|
|
|
|
if (cacti_sizeof($events)) {
|
|
foreach ($events as $e) {
|
|
$triggers[$option . '|' . $e['site_id']] = [
|
|
'events' => $e['hosts'],
|
|
'time' => $now
|
|
];
|
|
}
|
|
}
|
|
|
|
break;
|
|
case 'peg': // Percent of events Globally
|
|
$events = db_fetch_row_prepared('SELECT
|
|
(SELECT COUNT(*) FROM host WHERE disabled = "" AND deleted = "") AS total_hosts,
|
|
COUNT(nq.host_id) AS events
|
|
FROM notification_queue AS nq
|
|
INNER JOIN host AS h
|
|
ON h.id = nq.host_id
|
|
WHERE h.disabled = ""
|
|
AND h.deleted = ""
|
|
AND nq.event_processed = 0
|
|
AND nq.topic IN ("thold_dhost_mail", "thold_dhost_cmd")
|
|
AND nq.event_time BETWEEN ? AND ?
|
|
HAVING (events / total_hosts) * 100 > ?',
|
|
[
|
|
date('Y-m-d H:i:s', $last_check),
|
|
date('Y-m-d H:i:s', $now),
|
|
$value
|
|
]
|
|
);
|
|
|
|
if (cacti_sizeof($events)) {
|
|
$triggers[$option] = [
|
|
'events' => $events['events'],
|
|
'time' => $now
|
|
];
|
|
}
|
|
|
|
break;
|
|
default:
|
|
$events = [];
|
|
$triggers = [];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Review the old triggers first to see if the trigger period is over
|
|
* and it's time to provide final notification and communication
|
|
*
|
|
* This function will provide initial notification to the notification
|
|
* list associated with the devices of the initial event.
|
|
*/
|
|
check_for_expired_delays($last_trigger, $triggers, $now, $last_check);
|
|
|
|
/**
|
|
* Review the new triggers now to see if there are any new triggers
|
|
* and to setup notification delay for them. The prior step will
|
|
* unset any active triggers leaving only new triggers to setup
|
|
* and deal with.
|
|
*
|
|
* This function will also provide any final notification and set the
|
|
* JSON config option for future notification delay actions
|
|
*/
|
|
check_for_new_delays($last_trigger, $triggers, $now, $last_check);
|
|
}
|
|
|
|
/**
|
|
* check_for_expired_delays - This function will look at the start time of
|
|
* any trigger delays, and if the delay time has expired, it will check
|
|
* the status of the hosts in question, and if they are still in a down
|
|
* state, a final notification will be sent via Email and or Command with
|
|
*
|
|
* @param array - Any active triggers that may or may not remain active
|
|
* @param array - Any new triggers that may be part of an existing delay
|
|
* or a new delay based upon the ruleset.
|
|
* @param int - The Unix Timestamp of the start time for the sample period
|
|
* @param int - The Unix Timestamp of the last time that a check was performed.
|
|
* @param mixed $last_trigger
|
|
* @param mixed $triggers
|
|
* @param mixed $now
|
|
* @param mixed $last_check
|
|
*
|
|
* @return null - Though the two trigger variables that were passed by reference
|
|
* will be modified based upon the findings. For example, if a
|
|
* delay has expired and we provided notification the delay will
|
|
* be unset, also if we find additional events for and existing
|
|
* delay, it will be removed from the new events.
|
|
*/
|
|
function check_for_expired_delays(&$last_trigger, $triggers, $now, $last_check) {
|
|
$delay_period = read_config_option('alert_notification_delay');
|
|
|
|
if (cacti_sizeof($last_trigger)) {
|
|
foreach ($last_trigger as $type => $details) {
|
|
$parts = explode('|', $type);
|
|
|
|
/**
|
|
* Its time to provide the final notification for this notification
|
|
* delay. Check the type, the variout notification lists and the
|
|
* status of the hosts. If they are no longer down, you can cancel
|
|
* any notifications if not and send out an all clear event.
|
|
* Otherwise, trigger the notifications as directed.
|
|
*/
|
|
if ($now - $details['start_time'] >= $delay_period) {
|
|
switch($parts[0]) {
|
|
case 'eg':
|
|
case 'peg':
|
|
$hosts_down = db_fetch_assoc_prepared('SELECT h.*,
|
|
nq.id AS notification_id, nq.notification_list_id, nq.topic,
|
|
nq.event_data, nq.event_time
|
|
FROM host AS h
|
|
INNER JOIN notification_queue AS nq
|
|
ON h.id = nq.host_id
|
|
WHERE nq.event_processed = 0
|
|
AND nq.topic IN ("thold_dhost_mail", "thold_dhost_cmd")
|
|
AND nq.event_time BETWEEN ? AND ?
|
|
AND h.status NOT IN (?, ?)',
|
|
[
|
|
date('Y-m-d H:i:s', $details['start_time']),
|
|
date('Y-m-d H:i:s', $now),
|
|
HOST_RECOVERING,
|
|
HOST_UP
|
|
]
|
|
);
|
|
|
|
if (cacti_sizeof($hosts_down)) {
|
|
// perform notification of errors
|
|
$hosts = array_rekey($hosts_down, 'id', 'id');
|
|
} else {
|
|
// perform notification of clearing of errors
|
|
}
|
|
|
|
if (isset($triggers[$type])) {
|
|
unset($triggers[$type]);
|
|
}
|
|
|
|
break;
|
|
case 'es':
|
|
case 'pes':
|
|
$hosts_down = db_fetch_assoc_prepared('SELECT h.*,
|
|
nq.id AS notification_id, nq.notification_list_id, nq.topic,
|
|
nq.event_data, nq.event_time
|
|
FROM host AS h
|
|
INNER JOIN notification_queue AS nq
|
|
ON h.id = nq.host_id
|
|
WHERE nq.event_processed = 0
|
|
AND h.site_id = ?
|
|
AND nq.topic IN ("thold_dhost_mail", "thold_dhost_cmd")
|
|
AND nq.event_time BETWEEN ? AND ?
|
|
AND h.status NOT IN (?, ?)',
|
|
[
|
|
$parts[2],
|
|
date('Y-m-d H:i:s', $details['start_time']),
|
|
date('Y-m-d H:i:s', $now),
|
|
HOST_RECOVERING,
|
|
HOST_UP
|
|
]
|
|
);
|
|
|
|
if (cacti_sizeof($hosts_down)) {
|
|
// perform notification of errors
|
|
$hosts = array_rekey($hosts_down, 'id', 'id');
|
|
} else {
|
|
// perform notification of clearing of errors
|
|
}
|
|
|
|
if (isset($triggers[$type])) {
|
|
unset($triggers[$type]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* check_for_new_delays - Given the list of existing triggers and any
|
|
* new triggers, we will re-establish the triggers and provide the
|
|
* appropriate initial notification as required. The function in the
|
|
* end will set the config option for the next sampling interval to
|
|
* evaluate.
|
|
*
|
|
* @param array - Any active triggers that may or may not remain active
|
|
* @param array - Any new triggers that may be part of an existing delay
|
|
* or a new delay based upon the ruleset.
|
|
* @param int - The Unix Timestamp of the start time for the sample period
|
|
* @param int - The Unix Timestamp of the last time that a check was performed.
|
|
* @param mixed $last_trigger
|
|
* @param mixed $triggers
|
|
* @param mixed $now
|
|
* @param mixed $last_check
|
|
*
|
|
* @return null
|
|
*/
|
|
function check_for_new_delays($last_trigger, $triggers, $now, $last_check) {
|
|
$delay_period = read_config_option('alert_notification_delay');
|
|
}
|
|
|
|
function thold_notification_execute($pid = 0, $max_records = 'all') {
|
|
if ($max_records == 'all') {
|
|
$sql_limit = '';
|
|
} else {
|
|
$sql_limit = 'LIMIT ' . $max_records;
|
|
}
|
|
|
|
if ($pid > 0) {
|
|
$sql_where = ' AND process_id = ' . $pid;
|
|
} else {
|
|
$sql_where = '';
|
|
}
|
|
|
|
// See if and administrator has suspended notifications
|
|
$prev_suspended = read_config_option('thold_notification_suspended', true);
|
|
|
|
/**
|
|
* See if notification delay is active and mark the events as such,
|
|
* which will potentially leave less events to process.
|
|
* This process will also enable notification once the delay is over
|
|
* for the devices or allow them to be sent.
|
|
*/
|
|
pre_process_device_notifications($pid, $max_records);
|
|
|
|
/**
|
|
* Process any non-device up/down notifications first. These
|
|
* notifications are not subject to notification delay
|
|
*/
|
|
process_non_device_notifications($pid, $max_records, $prev_suspended);
|
|
|
|
/**
|
|
* Last process expired notification delays or device
|
|
* notifications that are not subject to notification delay
|
|
* not matching any rule type.
|
|
*/
|
|
process_device_notifications($pid, $max_records, $prev_suspended);
|
|
}
|
|
|
|
function process_device_notifications($pid, $max_records, $prev_suspended) {
|
|
$one_email = read_config_option('alert_deadnotify_one_mail') == 'on' ? true : false;
|
|
$emails = [];
|
|
|
|
if (!defined('TXT_SEP')) {
|
|
define('TXT_SEP', '----------------------------------------------------------');
|
|
}
|
|
|
|
if ($max_records == 'all') {
|
|
$sql_limit = '';
|
|
} else {
|
|
$sql_limit = 'LIMIT ' . $max_records;
|
|
}
|
|
|
|
if ($pid > 0) {
|
|
$sql_where = ' AND process_id = ' . $pid;
|
|
} else {
|
|
$sql_where = '';
|
|
}
|
|
|
|
$records = db_fetch_assoc("SELECT *
|
|
FROM notification_queue
|
|
WHERE event_processed = 0
|
|
AND topic IN ('thold_dhost_mail', 'thold_uhost_mail', 'thold_dhost_cmd', 'thold_uhost_cmd')
|
|
$sql_where
|
|
ORDER BY event_time ASC
|
|
$sql_limit");
|
|
|
|
if ($prev_suspended == 0) {
|
|
foreach ($records as $index => $r) {
|
|
$nstart = microtime(true);
|
|
|
|
// if notification is suspended, break from this loop
|
|
$suspended = read_config_option('thold_notification_suspended', true);
|
|
|
|
if ($suspended == 1) {
|
|
if ($prev_suspended == 0) {
|
|
debounce_run_notification('notify_suspend', 'WARNING: Notifications have been suspended by an operator. Returning from processing loop');
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
$topic = $r['topic'];
|
|
$processed = false;
|
|
|
|
if ($one_email) {
|
|
$host_subject = read_config_option('alert_deadnotify_subject');
|
|
|
|
if ($host_subject == '') {
|
|
$host_subject = 'Thold Device Notification: Up/Down Devices Found';
|
|
}
|
|
}
|
|
|
|
switch($topic) {
|
|
case 'thold_dhost_mail':
|
|
case 'thold_uhost_mail':
|
|
$data = json_decode($r['event_data'], true);
|
|
|
|
$attributes = [
|
|
'from', 'to', 'cc', 'bcc', 'replyto', 'subject', 'body', 'body_text', 'attachments', 'headers', 'html'
|
|
];
|
|
|
|
foreach ($attributes as $a) {
|
|
if (isset($data[$a])) {
|
|
$$a = $data[$a];
|
|
} else {
|
|
$$a = '';
|
|
}
|
|
}
|
|
|
|
// reverse the base64 encoding
|
|
if (cacti_sizeof($attachments)) {
|
|
foreach ($attachments as $index => $attach) {
|
|
$attachments[$index]['attachment'] = base64_decode($attach['attachment'], true);
|
|
}
|
|
}
|
|
|
|
if (!$one_email) {
|
|
$error = mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_text, $attachments, $headers, $html);
|
|
|
|
if ($error != '') {
|
|
cacti_log("ERROR: Sending Email Failed To:$to Subject:$subject. Error was:'$error'", true, 'THOLD');
|
|
|
|
$any_error = $error;
|
|
$error_code = 1;
|
|
} else {
|
|
$error_code = 0;
|
|
}
|
|
|
|
$nend = microtime(true);
|
|
|
|
db_execute_prepared('UPDATE notification_queue
|
|
SET error_code = ?, error_message = ?, event_processed = 1, event_processed_time=NOW(), event_processed_runtime = ?
|
|
WHERE id = ?',
|
|
[$error_code, str_replace("\n", ' ', $error), $nend - $nstart, $r['id']]);
|
|
} else {
|
|
$id = md5(json_encode([$from, $to, $cc, $bcc, $replyto]));
|
|
|
|
if (!isset($emails[$id])) {
|
|
$emails[$id]['from'] = $from;
|
|
$emails[$id]['to'] = $to;
|
|
$emails[$id]['cc'] = $cc;
|
|
$emails[$id]['bcc'] = $bcc;
|
|
$emails[$id]['replyto'] = $replyto;
|
|
$emails[$id]['subject'] = $host_subject;
|
|
$emails[$id]['body_text'] = $body_text;
|
|
$emails[$id]['body'] = str_replace(['<body>', '</body>'], '', $body);
|
|
$emails[$id]['pre_body'] = $subject;
|
|
$emails[$id]['pre_body_text'] = $subject;
|
|
$emails[$id]['html'] = $html;
|
|
$emails[$id]['headers'] = $headers;
|
|
|
|
if (cacti_sizeof($attachments)) {
|
|
$emails[$id]['attachments'] = $attachments;
|
|
} else {
|
|
$emails[$id]['attachments'] = [];
|
|
}
|
|
} else {
|
|
$emails[$id]['body_text'] .= PHP_EOL . TXT_SEP . PHP_EOL . $body_text;
|
|
$emails[$id]['body'] .= str_replace(['<body>', '</body>'], '', $body);
|
|
$emails[$id]['pre_body_text'] .= PHP_EOL . $subject;
|
|
$emails[$id]['pre_body'] .= '<br>' . $subject;
|
|
|
|
if (cacti_sizeof($attachments)) {
|
|
$emails[$id]['attachments'] += array_merge($emails['id']['attachments'], $attachments);
|
|
}
|
|
}
|
|
|
|
$emails[$id]['ids'][] = $r['id'];
|
|
}
|
|
|
|
break;
|
|
case 'thold_dhost_cmd':
|
|
case 'thold_uhost_cmd':
|
|
$data = json_decode($r['event_data'], true);
|
|
|
|
$attributes = [
|
|
'environment', 'command', 'data'
|
|
];
|
|
|
|
foreach ($attributes as $a) {
|
|
if (isset($data[$a])) {
|
|
$$a = $data[$a];
|
|
} else {
|
|
$$a = '';
|
|
}
|
|
}
|
|
|
|
$output = [];
|
|
$return = 0;
|
|
|
|
if (cacti_sizeof($data['environment'])) {
|
|
foreach ($data['environment'] as $e) {
|
|
putenv($e);
|
|
}
|
|
}
|
|
|
|
exec($command, $output, $return);
|
|
|
|
thold_process_command_output($output, $return, $topic, $data, $command);
|
|
|
|
$nend = microtime(true);
|
|
|
|
db_execute_prepared('UPDATE notification_queue
|
|
SET error_code = ?, error_message = ?, event_processed = 1, event_processed_time=NOW(), event_processed_runtime = ?
|
|
WHERE id = ?',
|
|
[$return, implode("\n", $output), $nend - $nstart, $r['id']]);
|
|
|
|
break;
|
|
default:
|
|
cacti_log(sprintf('ERROR: Unable to process Thold Notification of topic %s', $topic), false, 'THOLD');
|
|
}
|
|
}
|
|
|
|
if (cacti_sizeof($emails) && $one_email) {
|
|
foreach ($emails as $email) {
|
|
$attachments = [];
|
|
$from = $email['from'];
|
|
$to = $email['to'];
|
|
$cc = $email['cc'];
|
|
$bcc = $email['bcc'];
|
|
$replyto = $email['replyto'];
|
|
$subject = $email['subject'];
|
|
$body = $email['body'];
|
|
$body_text = $email['body_text'];
|
|
$headers = $email['headers'];
|
|
$html = $email['html'];
|
|
$pre_body = $email['pre_body'];
|
|
$pre_body_text = $email['pre_body_text'];
|
|
|
|
if (cacti_sizeof($email['attachments'])) {
|
|
foreach ($email['attachments'] as $index => $attach) {
|
|
$attachments[$index]['attachment'] = base64_decode($attach['attachment'], true);
|
|
}
|
|
}
|
|
|
|
$body = $pre_body . '<br><hr><br>' . $body;
|
|
$body_text = $pre_body_text . PHP_EOL . PHP_EOL . $body_text;
|
|
|
|
cacti_log("NOTE: Sending One Email Device Notification to:$to, bcc:$bcc, from:{$from[0]}, subject: $subject", false, 'THOLD');
|
|
|
|
$error = mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_text, $attachments, $headers, $html);
|
|
|
|
if ($error != '') {
|
|
cacti_log("ERROR: Sending Email Failed To:$to Subject:$subject. Error was:'$error'", true, 'THOLD');
|
|
|
|
$any_error = $error;
|
|
$error_code = 1;
|
|
} else {
|
|
$error_code = 0;
|
|
}
|
|
|
|
$nend = microtime(true);
|
|
|
|
$ids = implode(', ', $email['ids']);
|
|
|
|
db_execute_prepared("UPDATE notification_queue
|
|
SET error_code = ?, error_message = ?, event_processed = 1, event_processed_time=NOW(), event_processed_runtime = ?
|
|
WHERE id IN ($ids)",
|
|
[$error_code, str_replace("\n", ' ', $error), $nend - $nstart]);
|
|
}
|
|
}
|
|
} else {
|
|
debounce_run_notification('notify_suspend', 'WARNING: Notifications have been suspended by an operator. Returning from processing loop');
|
|
}
|
|
}
|
|
|
|
function process_non_device_notifications($pid, $max_records, $prev_suspended) {
|
|
if ($max_records == 'all') {
|
|
$sql_limit = '';
|
|
} else {
|
|
$sql_limit = 'LIMIT ' . $max_records;
|
|
}
|
|
|
|
if ($pid > 0) {
|
|
$sql_where = ' AND process_id = ' . $pid;
|
|
} else {
|
|
$sql_where = '';
|
|
}
|
|
|
|
$records = db_fetch_assoc("SELECT *
|
|
FROM notification_queue
|
|
WHERE event_processed = 0
|
|
AND topic NOT IN ('thold_dhost_mail', 'thold_uhost_mail', 'thold_dhost_cmd', 'thold_uhost_cmd')
|
|
$sql_where
|
|
ORDER BY event_time ASC
|
|
$sql_limit");
|
|
|
|
if ($prev_suspended == 0) {
|
|
foreach ($records as $r) {
|
|
$nstart = microtime(true);
|
|
|
|
// if notification is suspended, break from this loop
|
|
$suspended = read_config_option('thold_notification_suspended', true);
|
|
|
|
if ($suspended == 1) {
|
|
if ($prev_suspended == 0) {
|
|
debounce_run_notification('notify_suspend', 'WARNING: Notifications have been suspended by an operator. Returning from processing loop');
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
$topic = $r['topic'];
|
|
$processed = false;
|
|
|
|
switch($topic) {
|
|
case 'thold_mail':
|
|
$data = json_decode($r['event_data'], true);
|
|
|
|
$attributes = [
|
|
'from', 'to', 'cc', 'bcc', 'replyto', 'subject', 'body', 'body_text', 'attachments', 'headers', 'html'
|
|
];
|
|
|
|
foreach ($attributes as $a) {
|
|
if (isset($data[$a])) {
|
|
$$a = $data[$a];
|
|
} else {
|
|
$$a = '';
|
|
}
|
|
}
|
|
|
|
if (cacti_sizeof($attachments)) {
|
|
foreach ($attachments as $index => $attach) {
|
|
$attachments[$index]['attachment'] = base64_decode($attach['attachment'], true);
|
|
}
|
|
}
|
|
|
|
$error = mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_text, $attachments, $headers, $html);
|
|
|
|
if ($error != '') {
|
|
cacti_log("ERROR: Sending Email Failed To:$to Subject:$subject. Error was:'$error'", true, 'THOLD');
|
|
|
|
$any_error = $error;
|
|
$error_code = 1;
|
|
} else {
|
|
$error_code = 0;
|
|
}
|
|
|
|
$nend = microtime(true);
|
|
|
|
db_execute_prepared('UPDATE notification_queue
|
|
SET error_code = ?, error_message = ?, event_processed = 1, event_processed_time=NOW(), event_processed_runtime = ?
|
|
WHERE id = ?',
|
|
[$error_code, str_replace("\n", ' ', $error), $nend - $nstart, $r['id']]);
|
|
|
|
break;
|
|
case 'thold_cmd':
|
|
$data = json_decode($r['event_data'], true);
|
|
|
|
$attributes = [
|
|
'environment', 'command', 'data'
|
|
];
|
|
|
|
foreach ($attributes as $a) {
|
|
if (isset($data[$a])) {
|
|
$$a = $data[$a];
|
|
} else {
|
|
$$a = '';
|
|
}
|
|
}
|
|
|
|
$output = [];
|
|
$return = 0;
|
|
|
|
if (cacti_sizeof($data['environment'])) {
|
|
foreach ($data['environment'] as $e) {
|
|
putenv($e);
|
|
}
|
|
}
|
|
|
|
exec($command, $output, $return);
|
|
|
|
thold_process_command_output($output, $return, $topic, $data, $command);
|
|
|
|
$nend = microtime(true);
|
|
|
|
db_execute_prepared('UPDATE notification_queue
|
|
SET error_code = ?, error_message = ?, event_processed = 1, event_processed_time=NOW(), event_processed_runtime = ?
|
|
WHERE id = ?',
|
|
[$return, implode("\n", $output), $nend - $nstart, $r['id']]);
|
|
|
|
break;
|
|
default:
|
|
cacti_log(sprintf('ERROR: Unable to process Thold Notification of topic %s', $topic), false, 'THOLD');
|
|
}
|
|
}
|
|
} else {
|
|
debounce_run_notification('notify_suspend', 'WARNING: Notifications have been suspended by an operator. Returning from processing loop');
|
|
}
|
|
}
|
|
|
|
function thold_template_update_threshold($id, $template) {
|
|
db_execute_prepared("UPDATE thold_data AS td, thold_template AS tt
|
|
SET
|
|
td.name = tt.suggested_name, td.thold_hi = tt.thold_hi,
|
|
td.data_source_name = tt.data_source_name, td.data_template_hash = tt.data_template_hash,
|
|
td.data_template_id = tt.data_template_id, td.thold_low = tt.thold_low,
|
|
td.thold_fail_trigger = tt.thold_fail_trigger, td.time_hi = tt.time_hi, td.time_low = tt.time_low,
|
|
td.time_fail_trigger = tt.time_fail_trigger, td.time_fail_length = tt.time_fail_length,
|
|
td.thold_warning_hi = tt.thold_warning_hi, td.thold_warning_low = tt.thold_warning_low,
|
|
td.thold_warning_fail_trigger = tt.thold_warning_fail_trigger, td.time_warning_hi = tt.time_warning_hi,
|
|
td.time_warning_low = tt.time_warning_low, td.time_warning_fail_trigger = tt.time_warning_fail_trigger,
|
|
td.time_warning_fail_length = tt.time_warning_fail_length, td.thold_enabled = tt.thold_enabled,
|
|
td.thold_type = tt.thold_type, td.bl_type = tt.bl_type, td.bl_cf = tt.bl_cf, td.bl_ref_time_range = tt.bl_ref_time_range,
|
|
td.bl_pct_up = tt.bl_pct_up, td.bl_pct_down = tt.bl_pct_down, td.bl_pct_up = tt.bl_pct_up,
|
|
td.bl_fail_trigger = tt.bl_fail_trigger, td.bl_alert = tt.bl_alert, td.bl_thold_valid = 0,
|
|
td.repeat_alert = tt.repeat_alert, td.data_type = tt.data_type, td.cdef = tt.cdef,
|
|
td.percent_ds = tt.percent_ds, td.expression = tt.expression, td.upper_ds = tt.upper_ds,
|
|
td.exempt = tt.exempt, td.reset_ack = tt.reset_ack, td.persist_ack = tt.persist_ack,
|
|
td.thold_hrule_alert = tt.thold_hrule_alert, td.thold_hrule_warning = tt.thold_hrule_warning,
|
|
td.skipscale = tt.skipscale, td.restored_alert = tt.restored_alert,
|
|
td.email_subject = tt.email_subject, td.email_subject_warn = tt.email_subject_warn,
|
|
td.email_subject_restoral = tt.email_subject_restoral, td.email_body = tt.email_body,
|
|
td.email_body_warn = tt.email_body_warn, td.email_body_restoral = tt.email_body_restoral,
|
|
td.trigger_cmd_high = tt.trigger_cmd_high, td.trigger_cmd_low = tt.trigger_cmd_low,
|
|
td.trigger_cmd_norm = tt.trigger_cmd_norm, td.syslog_enabled = tt.syslog_enabled,
|
|
td.syslog_priority = tt.syslog_priority, td.syslog_facility = tt.syslog_facility,
|
|
td.snmp_event_category = tt.snmp_event_category, td.snmp_event_description = tt.snmp_event_description,
|
|
td.snmp_event_severity = tt.snmp_event_severity, td.snmp_event_warning_severity = tt.snmp_event_warning_severity,
|
|
td.notes = tt.notes, td.external_id = tt.external_id, td.format_file = tt.format_file,
|
|
td.graph_timespan = tt.graph_timespan
|
|
WHERE td.id = ?
|
|
AND td.template_enabled = 'on'
|
|
AND tt.id = ?",
|
|
[$id, $template]);
|
|
|
|
db_execute_prepared('DELETE FROM plugin_thold_threshold_contact
|
|
WHERE thold_id = ?',
|
|
[$id]);
|
|
|
|
db_execute_prepared('INSERT INTO plugin_thold_threshold_contact
|
|
(thold_id, contact_id)
|
|
SELECT ?, contact_id
|
|
FROM plugin_thold_template_contact
|
|
WHERE template_id = ?',
|
|
[$id, $template]);
|
|
|
|
update_notification_list_from_template($template, $id);
|
|
|
|
update_suggested_names_from_template($template, $id);
|
|
}
|
|
|
|
function thold_template_update_thresholds($id) {
|
|
db_execute_prepared("UPDATE thold_data AS td, thold_template AS tt
|
|
SET
|
|
td.name = tt.suggested_name, td.thold_hi = tt.thold_hi, td.data_source_name = tt.data_source_name,
|
|
td.data_template_hash = tt.data_template_hash, td.data_template_id = tt.data_template_id,
|
|
td.thold_low = tt.thold_low, td.thold_fail_trigger = tt.thold_fail_trigger, td.time_hi = tt.time_hi,
|
|
td.time_low = tt.time_low, td.time_fail_trigger = tt.time_fail_trigger,
|
|
td.time_fail_length = tt.time_fail_length, td.thold_warning_hi = tt.thold_warning_hi,
|
|
td.thold_warning_low = tt.thold_warning_low, td.thold_warning_fail_trigger = tt.thold_warning_fail_trigger,
|
|
td.time_warning_hi = tt.time_warning_hi, td.time_warning_low = tt.time_warning_low,
|
|
td.time_warning_fail_trigger = tt.time_warning_fail_trigger, td.time_warning_fail_length = tt.time_warning_fail_length,
|
|
td.thold_enabled = tt.thold_enabled, td.thold_type = tt.thold_type,
|
|
td.bl_type = tt.bl_type, td.bl_cf = tt.bl_cf, td.bl_ref_time_range = tt.bl_ref_time_range,
|
|
td.bl_pct_up = tt.bl_pct_up, td.bl_pct_down = tt.bl_pct_down, td.bl_pct_up = tt.bl_pct_up,
|
|
td.bl_fail_trigger = tt.bl_fail_trigger, td.bl_alert = tt.bl_alert, td.bl_thold_valid = 0,
|
|
td.repeat_alert = tt.repeat_alert, td.data_type = tt.data_type, td.cdef = tt.cdef,
|
|
td.percent_ds = tt.percent_ds, td.expression = tt.expression, td.upper_ds = tt.upper_ds, td.show_units = tt.show_units,
|
|
td.units_suffix = tt.units_suffix, td.decimals = tt.decimals, td.exempt = tt.exempt,
|
|
td.reset_ack = tt.reset_ack, td.persist_ack = tt.persist_ack,
|
|
td.thold_hrule_alert = tt.thold_hrule_alert, td.thold_hrule_warning = tt.thold_hrule_warning,
|
|
td.skipscale = tt.skipscale, td.restored_alert = tt.restored_alert,
|
|
td.email_subject = tt.email_subject, td.email_subject_warn = tt.email_subject_warn,
|
|
td.email_subject_restoral = tt.email_subject_restoral, td.email_body = tt.email_body,
|
|
td.email_body_warn = tt.email_body_warn, td.email_body_restoral = tt.email_body_restoral,
|
|
td.trigger_cmd_high = tt.trigger_cmd_high, td.trigger_cmd_low = tt.trigger_cmd_low, td.trigger_cmd_norm = tt.trigger_cmd_norm,
|
|
td.syslog_enabled = tt.syslog_enabled, td.syslog_priority = tt.syslog_priority,
|
|
td.syslog_facility = tt.syslog_facility,
|
|
td.snmp_event_category = tt.snmp_event_category, td.snmp_event_description = tt.snmp_event_description,
|
|
td.snmp_event_severity = tt.snmp_event_severity, td.snmp_event_warning_severity = tt.snmp_event_warning_severity,
|
|
td.notes = tt.notes, td.external_id = tt.external_id, td.format_file = tt.format_file,
|
|
td.graph_timespan = tt.graph_timespan
|
|
WHERE td.thold_template_id = ?
|
|
AND td.template_enabled = 'on'
|
|
AND tt.id = ?",
|
|
[$id, $id]);
|
|
|
|
$rows = db_fetch_assoc_prepared("SELECT id, thold_template_id
|
|
FROM thold_data
|
|
WHERE thold_data.thold_template_id = ?
|
|
AND thold_data.template_enabled = 'on'",
|
|
[$id]);
|
|
|
|
if (cacti_sizeof($rows)) {
|
|
foreach ($rows as $row) {
|
|
db_execute_prepared('DELETE FROM plugin_thold_threshold_contact
|
|
WHERE thold_id = ?',
|
|
[$row['id']]);
|
|
|
|
db_execute_prepared('INSERT INTO plugin_thold_threshold_contact
|
|
(thold_id, contact_id)
|
|
SELECT ?, contact_id
|
|
FROM plugin_thold_template_contact
|
|
WHERE template_id = ?',
|
|
[$row['id'], $row['thold_template_id']]);
|
|
}
|
|
}
|
|
|
|
update_notification_list_from_template($id);
|
|
|
|
update_suggested_names_from_template($id);
|
|
}
|
|
|
|
function update_notification_list_from_template($id, $thold_id = -1) {
|
|
$templated = db_fetch_cell_prepared('SELECT notify_templated
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
if ($thold_id > 0) {
|
|
$sql_where = ' AND td.id = ' . $thold_id;
|
|
} else {
|
|
$sql_where = '';
|
|
}
|
|
|
|
if ($templated == 'on') {
|
|
db_execute_prepared("UPDATE thold_data AS td, thold_template AS tt
|
|
SET
|
|
td.notify_warning = tt.notify_warning, td.notify_alert = tt.notify_alert,
|
|
td.notify_extra = tt.notify_extra, td.notify_warning_extra = tt.notify_warning_extra
|
|
WHERE td.thold_template_id = ?
|
|
AND td.template_enabled = 'on'
|
|
AND tt.id = ?" . $sql_where,
|
|
[$id, $id]);
|
|
}
|
|
}
|
|
|
|
function update_suggested_names_from_template($id, $thold_id = -1) {
|
|
$suggested_name = db_fetch_cell_prepared('SELECT suggested_name
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
if ($thold_id > 0) {
|
|
$sql_where = ' AND id = ' . $thold_id;
|
|
} else {
|
|
$sql_where = '';
|
|
}
|
|
|
|
$tholds = db_fetch_assoc_prepared('SELECT *
|
|
FROM thold_data
|
|
WHERE template_enabled = "on"
|
|
AND thold_template_id = ?' . $sql_where,
|
|
[$id]);
|
|
|
|
if (cacti_sizeof($tholds)) {
|
|
foreach ($tholds as $thold_data) {
|
|
$name_cache = thold_expand_string($thold_data, $suggested_name);
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET name_cache = ?
|
|
WHERE id = ?',
|
|
[$name_cache, $thold_data['id']]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_cacti_log($string, $thread = '', $stdout = false) {
|
|
global $config, $debug;
|
|
static $start = null;
|
|
|
|
$environ = 'THOLD' . ($thread != '' ? ' THREAD[' . $thread . ']' : '');
|
|
|
|
// fill in the current date for printing in the log
|
|
if (defined('CACTI_DATE_TIME_FORMAT')) {
|
|
$date = date(CACTI_DATE_TIME_FORMAT);
|
|
} else {
|
|
$date = date('Y-m-d H:i:s');
|
|
}
|
|
|
|
// determine how to log data
|
|
$logdestination = read_config_option('log_destination');
|
|
$logfile = read_config_option('path_cactilog');
|
|
|
|
// format the message
|
|
if ($stdout) {
|
|
if ($start == null) {
|
|
$start = microtime(true);
|
|
$total = 0.00;
|
|
} else {
|
|
$total = microtime(true) - $start;
|
|
}
|
|
|
|
if (!$debug) {
|
|
printf('Total[%0.4f] - %s: %s' . PHP_EOL, $total, $environ, trim($string));
|
|
} else {
|
|
printf('Total[%0.4f] DEBUG: %s' . PHP_EOL, $total, trim($string));
|
|
}
|
|
}
|
|
|
|
$message = "$date - " . $environ . ': ' . trim($string) . "\n";
|
|
|
|
// Log to Logfile
|
|
if ((($logdestination == 1) || ($logdestination == 2)) && (read_config_option('log_verbosity') != POLLER_VERBOSITY_NONE)) {
|
|
if ($logfile == '') {
|
|
$logfile = $config['base_path'] . '/log/cacti.log';
|
|
}
|
|
|
|
// print the data to the log (append)
|
|
$fp = @fopen($logfile, 'a');
|
|
|
|
if ($fp) {
|
|
@fwrite($fp, $message);
|
|
fclose($fp);
|
|
}
|
|
}
|
|
|
|
// Log to Syslog/Eventlog
|
|
// Syslog is currently Unstable in Win32
|
|
if (($logdestination == 2) || ($logdestination == 3)) {
|
|
$string = strip_tags($string);
|
|
$log_type = '';
|
|
|
|
if (substr_count($string,'ERROR:')) {
|
|
$log_type = 'err';
|
|
} elseif (substr_count($string,'WARNING:')) {
|
|
$log_type = 'warn';
|
|
} elseif (substr_count($string,'STATS:')) {
|
|
$log_type = 'stat';
|
|
} elseif (substr_count($string,'NOTICE:')) {
|
|
$log_type = 'note';
|
|
}
|
|
|
|
if (strlen($log_type)) {
|
|
if ($config['cacti_server_os'] == 'win32') {
|
|
openlog('Cacti', LOG_NDELAY | LOG_PID, LOG_USER);
|
|
} else {
|
|
openlog('Cacti', LOG_NDELAY | LOG_PID, LOG_SYSLOG);
|
|
}
|
|
|
|
if (($log_type == 'err') && (read_config_option('log_perror'))) {
|
|
syslog(LOG_CRIT, $environ . ': ' . $string);
|
|
}
|
|
|
|
if (($log_type == 'warn') && (read_config_option('log_pwarn'))) {
|
|
syslog(LOG_WARNING, $environ . ': ' . $string);
|
|
}
|
|
|
|
if ((($log_type == 'stat') || ($log_type == 'note')) && (read_config_option('log_pstats'))) {
|
|
syslog(LOG_INFO, $environ . ': ' . $string);
|
|
}
|
|
|
|
closelog();
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_threshold_enable($id) {
|
|
if (api_user_realm_auth('thold.php')) {
|
|
db_execute_prepared("UPDATE thold_data
|
|
SET thold_per_enabled = 'on',
|
|
thold_fail_count = 0,
|
|
thold_warning_fail_count = 0,
|
|
bl_fail_count = 0,
|
|
thold_alert = 0,
|
|
bl_alert = 0
|
|
WHERE id = ?",
|
|
[$id]);
|
|
}
|
|
}
|
|
|
|
function thold_threshold_disable($id) {
|
|
if (api_user_realm_auth('thold.php')) {
|
|
db_execute_prepared("UPDATE thold_data
|
|
SET thold_per_enabled = '',
|
|
thold_fail_count = 0,
|
|
thold_warning_fail_count = 0,
|
|
bl_fail_count = 0,
|
|
thold_alert = 0,
|
|
bl_alert = 0
|
|
WHERE id = ?",
|
|
[$id]);
|
|
}
|
|
}
|
|
|
|
function thold_threshold_ack_prompt($id) {
|
|
global $config;
|
|
|
|
top_header();
|
|
|
|
form_start($config['url_path'] . 'plugins/thold/thold_graph.php');
|
|
|
|
html_start_box(__('Acknowledge Threshold', 'thold'), '60%', '', '3', 'center', '');
|
|
|
|
$message = __('Click \'Continue\' to Acknowledge the following Threshold(s).', 'thold');
|
|
$button = __esc('Acknowledge Threshold(s)', 'thold');
|
|
|
|
print "<tr>
|
|
<td colspan='2'>
|
|
<p>$message</p>
|
|
</td>
|
|
</tr>";
|
|
|
|
print "<tr><td colspan='2'><p><i>Operator Message:</i><br><textarea class='ui-state-default ui-corner-all' style='width:70%;height:50px;' area-multiline='true' rows='2' id='message' name='message'></textarea></p></td></tr>";
|
|
|
|
$save_html = "<input type='button' class='ui-button ui-corner-all ui-widget' value='" . __esc('Cancel', 'thold') . "' onClick='cactiReturnTo()'>";
|
|
|
|
if (!empty($button)) {
|
|
$save_html .= " <input type='submit' class='ui-button ui-corner-all ui-widget' value='" . __esc('Continue', 'thold') . "' title='$button'>";
|
|
}
|
|
|
|
print "<tr>
|
|
<td colspan='2' class='saveRow'>
|
|
<input type='hidden' name='action' value='ack_confirm'>
|
|
<input type='hidden' name='threshold_id' value='$id'>
|
|
$save_html
|
|
</td>
|
|
</tr>";
|
|
|
|
html_end_box();
|
|
|
|
form_end();
|
|
|
|
bottom_footer();
|
|
}
|
|
|
|
function thold_threshold_ack($id) {
|
|
if (api_user_realm_auth('thold.php')) {
|
|
if (is_thold_allowed($id)) {
|
|
plugin_thold_log_changes($id, 'acknowledge_threshold', ['id' => $id]);
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment = ""
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
ack_logging($id, get_request_var('message'));
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_threshold_suspend_ack($id) {
|
|
if (api_user_realm_auth('thold.php')) {
|
|
if (is_thold_allowed($id)) {
|
|
plugin_thold_log_changes($id, 'suspend_acknowledge_threshold', ['id' => $id]);
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment=""
|
|
WHERE id = ?
|
|
AND reset_ack = "on"',
|
|
[$id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_threshold_resume_ack($id) {
|
|
if (api_user_realm_auth('thold.php')) {
|
|
if (is_thold_allowed($id)) {
|
|
plugin_thold_log_changes($id, 'resume_acknowledge_threshold', ['id' => $id]);
|
|
|
|
db_execute_prepared('UPDATE thold_data
|
|
SET acknowledgment="on"
|
|
WHERE id = ?
|
|
AND thold_alert > 0
|
|
AND reset_ack = "on"',
|
|
[$id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function get_thold_emails($thold, $class = 'alert', $recipient = 'to') {
|
|
$emails = '';
|
|
|
|
if ($class == 'alert') {
|
|
if (read_config_option('thold_disable_legacy') != 'on' && $recipient == 'to') {
|
|
$email_addresses = [];
|
|
|
|
$rows = db_fetch_assoc_prepared('SELECT ptc.data
|
|
FROM plugin_thold_contacts AS ptc
|
|
INNER JOIN plugin_thold_threshold_contact AS pttc
|
|
ON ptc.id = pttc.contact_id
|
|
WHERE pttc.thold_id = ?',
|
|
[$thold['id']]);
|
|
|
|
if (cacti_sizeof($rows)) {
|
|
foreach ($rows as $row) {
|
|
$email_addresses[] = $row['data'];
|
|
}
|
|
}
|
|
|
|
$emails = implode(',', $email_addresses);
|
|
|
|
if ($emails != '') {
|
|
$emails .= ',' . $thold['notify_extra'];
|
|
} else {
|
|
$emails = $thold['notify_extra'];
|
|
}
|
|
}
|
|
|
|
$emails .= ($emails != '' ? ',' : '') . get_thold_notification_emails($thold['notify_alert'], $recipient);
|
|
} else {
|
|
if (read_config_option('thold_disable_legacy') != 'on' && $recipient == 'to') {
|
|
$emails = $thold['notify_warning_extra'];
|
|
}
|
|
|
|
$emails .= ($emails != '' ? ',' : '') . get_thold_notification_emails($thold['notify_warning'], $recipient);
|
|
}
|
|
|
|
return $emails;
|
|
}
|
|
|
|
function get_thold_notification_emails($id = '', $recipient = 'to') {
|
|
if ($id == '' || $id === null) {
|
|
return '';
|
|
}
|
|
|
|
if (!thold_notification_list_enabled($id)) {
|
|
return '';
|
|
}
|
|
|
|
if (!empty($id)) {
|
|
if ($recipient == 'to') {
|
|
return trim(db_fetch_cell_prepared('SELECT emails
|
|
FROM plugin_notification_lists
|
|
WHERE id = ?',
|
|
[$id]));
|
|
} else {
|
|
return trim(db_fetch_cell_prepared('SELECT bcc_emails
|
|
FROM plugin_notification_lists
|
|
WHERE id = ?',
|
|
[$id]));
|
|
}
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
function thold_notification_list_enabled($list_id) {
|
|
static $lists = null;
|
|
|
|
if ($lists == null) {
|
|
$lists = array_rekey(
|
|
db_fetch_assoc('SELECT id, enabled
|
|
FROM plugin_notification_lists'),
|
|
'id', 'enabled'
|
|
);
|
|
}
|
|
|
|
if (isset($lists[$list_id])) {
|
|
return $lists[$list_id] == 'on';
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/** get_hash_thold_template - returns the current unique hash for a thold_template
|
|
* @param $id - (int) the ID of the thold template to return a hash for
|
|
* @param mixed $id
|
|
* @returns - a 128-bit, hexadecimal hash */
|
|
function get_hash_thold_template($id) {
|
|
$hash = db_fetch_cell_prepared('SELECT hash
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$id]);
|
|
|
|
if (preg_match('/[a-fA-F0-9]{32}/', $hash)) {
|
|
return $hash;
|
|
} else {
|
|
return generate_hash();
|
|
}
|
|
}
|
|
|
|
function ia2xml($array) {
|
|
$xml = '';
|
|
|
|
if (cacti_sizeof($array)) {
|
|
foreach ($array as $key=>$value) {
|
|
if (is_array($value)) {
|
|
$xml .= "\t<$key>" . ia2xml($value) . "</$key>\n";
|
|
} else {
|
|
$xml .= "\t<$key>" . html_escape($value) . "</$key>\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
return $xml;
|
|
}
|
|
|
|
function array2xml($array, $tag = 'template') {
|
|
static $index = 1;
|
|
|
|
$xml = "<$tag$index>\n" . ia2xml($array) . "</$tag$index>\n";
|
|
|
|
$index++;
|
|
|
|
return $xml;
|
|
}
|
|
|
|
function thold_snmptrap($varbinds, $severity = SNMPAGENT_EVENT_SEVERITY_MEDIUM, $overwrite = false) {
|
|
if (function_exists('snmpagent_notification')) {
|
|
if (isset($varbinds['eventDescription']) && isset($varbinds['eventDeviceIp'])) {
|
|
$varbinds['eventDescription'] = thold_str_replace('<HOSTIP>', $varbinds['eventDeviceIp'], $varbinds['eventDescription']);
|
|
}
|
|
|
|
snmpagent_notification('tholdNotify', 'CACTI-THOLD-MIB', $varbinds, $severity, $overwrite);
|
|
} else {
|
|
cacti_log('ERROR: THOLD was unable to generate SNMP notifications. Cacti SNMPAgent plugin is current missing or inactive.');
|
|
}
|
|
}
|
|
|
|
function thold_prune_old_data() {
|
|
// Remove failed entries from removed devices
|
|
db_execute('DELETE pthf
|
|
FROM plugin_thold_host_failed AS pthf
|
|
LEFT JOIN host AS h
|
|
ON pthf.host_id = h.id
|
|
WHERE h.id IS NULL');
|
|
|
|
if (db_affected_rows() > 0) {
|
|
set_config_option('time_last_change_thold_device', time());
|
|
}
|
|
|
|
$queue = read_config_option('thold_notification_queue');
|
|
|
|
// Remove log entries from removed devices
|
|
db_execute('DELETE ptl
|
|
FROM plugin_thold_log AS ptl
|
|
LEFT JOIN host AS h
|
|
ON ptl.host_id = h.id
|
|
WHERE h.id IS NULL');
|
|
|
|
if (db_affected_rows() > 0) {
|
|
set_config_option('time_last_change_thold_log', time());
|
|
set_config_option('time_last_change_thold', time());
|
|
}
|
|
|
|
// Remove thresholds from removed devices
|
|
db_execute('DELETE td
|
|
FROM thold_data AS td
|
|
LEFT JOIN host AS h
|
|
ON td.host_id = h.id
|
|
WHERE h.id IS NULL');
|
|
|
|
if (db_affected_rows() > 0) {
|
|
set_config_option('time_last_change_thold', time());
|
|
}
|
|
|
|
// Remove thresholds from removed graphs
|
|
db_execute('DELETE td
|
|
FROM thold_data AS td
|
|
LEFT JOIN graph_local AS gl
|
|
ON td.local_graph_id = gl.id
|
|
WHERE gl.id IS NULL');
|
|
|
|
if (db_affected_rows() > 0) {
|
|
set_config_option('time_last_change_thold', time());
|
|
}
|
|
|
|
if ($queue == 'on') {
|
|
db_execute('DELETE FROM notification_queue
|
|
WHERE event_processed = 1
|
|
AND event_processed_time < FROM_UNIXTIME(UNIX_TIMESTAMP()-3600)');
|
|
|
|
if (db_affected_rows() > 0) {
|
|
db_execute('OPTIMIZE TABLE notification_queue');
|
|
}
|
|
}
|
|
}
|
|
|
|
function thold_get_allowed_devices($sql_where = '', $order_by = 'description', $sql_limit = '', &$total_rows = 0, $user_id = 0, $device_id = 0) {
|
|
if ($user_id == -1) {
|
|
$auth_method = 0;
|
|
} else {
|
|
$auth_method = read_config_option('auth_method');
|
|
}
|
|
|
|
if ($user_id == 0) {
|
|
if (isset($_SESSION['sess_user_id'])) {
|
|
$user_id = $_SESSION['sess_user_id'];
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
$simple_perms = get_simple_device_perms($user_id);
|
|
|
|
$init_rows = $total_rows;
|
|
|
|
$host_list = [];
|
|
|
|
if ($sql_limit != '' && $sql_limit != -1) {
|
|
$sql_limit = "LIMIT $sql_limit";
|
|
} else {
|
|
$sql_limit = '';
|
|
}
|
|
|
|
if ($order_by != '') {
|
|
$order_by = "ORDER BY $order_by";
|
|
}
|
|
|
|
if (read_user_setting('hide_disabled') == 'on') {
|
|
$sql_where .= ($sql_where != '' ? ' AND' : '') . ' (h.disabled = "" OR h.disabled IS NULL)';
|
|
}
|
|
|
|
if ($sql_where != '') {
|
|
$sql_where = "WHERE $sql_where";
|
|
}
|
|
|
|
if ($device_id > 0) {
|
|
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . " h.id = $device_id";
|
|
}
|
|
|
|
$graph_auth_method = read_config_option('graph_auth_method');
|
|
|
|
$poller_interval = read_config_option('poller_interval');
|
|
|
|
// get policies for all groups and user
|
|
$policies = get_policies($user_id);
|
|
|
|
if (!$simple_perms && $auth_method != 0) {
|
|
$sql_where = get_policy_where($graph_auth_method, $policies, $sql_where);
|
|
}
|
|
|
|
if (db_column_exists('host', 'graphs')) {
|
|
$host_list = db_fetch_assoc("SELECT h1.*, graphs, data_sources,
|
|
CAST(IF(availability_method = 0, '0',
|
|
IF(status_event_count > 0 AND status IN (1, 2), status_event_count*$poller_interval,
|
|
IF(UNIX_TIMESTAMP(status_rec_date) < 943916400 AND status IN (0, 3), total_polls*$poller_interval,
|
|
IF(UNIX_TIMESTAMP(status_rec_date) > 943916400, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(status_rec_date),
|
|
IF(snmp_sysUptimeInstance>0 AND snmp_version > 0, snmp_sysUptimeInstance/100, UNIX_TIMESTAMP()
|
|
))))) AS unsigned) AS instate
|
|
FROM host AS h1
|
|
INNER JOIN (
|
|
SELECT DISTINCT id
|
|
FROM (
|
|
SELECT h.id
|
|
FROM host AS h
|
|
LEFT JOIN graph_local AS gl
|
|
ON h.id = gl.host_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id = gl.graph_template_id
|
|
LEFT JOIN host_template AS ht
|
|
ON h.host_template_id = ht.id
|
|
$sql_where
|
|
) AS rs1
|
|
) AS rs2
|
|
ON rs2.id = h1.id
|
|
$order_by
|
|
$sql_limit"
|
|
);
|
|
|
|
$sql = "SELECT COUNT(DISTINCT id)
|
|
FROM (
|
|
SELECT h.id
|
|
FROM host AS h
|
|
LEFT JOIN graph_local AS gl
|
|
ON h.id = gl.host_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id = gl.graph_template_id
|
|
LEFT JOIN host_template AS ht
|
|
ON h.host_template_id = ht.id
|
|
$sql_where
|
|
) AS rower";
|
|
} else {
|
|
$host_list = db_fetch_assoc("SELECT h1.*, graphs, data_sources,
|
|
CAST(IF(availability_method = 0, '0',
|
|
IF(status_event_count > 0 AND status IN (1, 2), status_event_count*$poller_interval,
|
|
IF(UNIX_TIMESTAMP(status_rec_date) < 943916400 AND status IN (0, 3), total_polls*$poller_interval,
|
|
IF(UNIX_TIMESTAMP(status_rec_date) > 943916400, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(status_rec_date),
|
|
IF(snmp_sysUptimeInstance>0 AND snmp_version > 0, snmp_sysUptimeInstance/100, UNIX_TIMESTAMP()
|
|
))))) AS unsigned) AS instate
|
|
FROM host AS h1
|
|
INNER JOIN (
|
|
SELECT DISTINCT id
|
|
FROM (
|
|
SELECT h.id
|
|
FROM host AS h
|
|
LEFT JOIN graph_local AS gl
|
|
ON h.id = gl.host_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id = gl.graph_template_id
|
|
LEFT JOIN host_template AS ht
|
|
ON h.host_template_id = ht.id
|
|
$sql_where
|
|
) AS rs1
|
|
) AS rs2
|
|
ON rs2.id = h1.id
|
|
LEFT JOIN (SELECT host_id, COUNT(*) AS graphs FROM graph_local GROUP BY host_id) AS gl
|
|
ON h1.id = gl.host_id
|
|
LEFT JOIN (SELECT host_id, COUNT(*) AS data_sources FROM data_local GROUP BY host_id) AS dl
|
|
ON h1.id = dl.host_id
|
|
$order_by
|
|
$sql_limit"
|
|
);
|
|
|
|
$sql = "SELECT COUNT(DISTINCT id)
|
|
FROM (
|
|
SELECT h.id
|
|
FROM host AS h
|
|
LEFT JOIN graph_local AS gl
|
|
ON h.id = gl.host_id
|
|
LEFT JOIN graph_templates AS gt
|
|
ON gt.id = gl.graph_template_id
|
|
LEFT JOIN host_template AS ht
|
|
ON h.host_template_id = ht.id
|
|
$sql_where
|
|
) AS rower";
|
|
}
|
|
|
|
if (function_exists('get_total_row_data') && $device_id == 0) {
|
|
$total_rows = get_total_row_data($user_id, $sql, [], 'thold_device', 10);
|
|
} else {
|
|
$total_rows = db_fetch_cell($sql);
|
|
}
|
|
|
|
return $host_list;
|
|
}
|
|
|
|
function thold_get_default_template_name($thold_data) {
|
|
return $thold_data['data_template_name'] . ' [' . $thold_data['data_source_name'] . ']';
|
|
}
|
|
|
|
function thold_get_default_suggested_name($thold_data, $id = 0) {
|
|
if (empty($thold_data) && $id) {
|
|
$thold_data = db_fetch_row_prepared('SELECT suggested_name
|
|
FROM thold_template
|
|
WHERE id = ?',
|
|
[$id]);
|
|
}
|
|
|
|
$desc = '|data_source_description| [|data_source_name|]';
|
|
|
|
if (isset($thold_data['suggested_name']) && !empty($thold_data['suggested_name'])) {
|
|
$desc = $thold_data['suggested_name'];
|
|
}
|
|
|
|
return $desc;
|
|
}
|
|
|
|
function thold_get_cached_name(&$thold_data) {
|
|
if (empty($thold_data['name_cache'])) {
|
|
$thold_data['name_cache'] = thold_substitute_data_source_description($thold_data['name'], $thold_data['local_data_id']);
|
|
}
|
|
|
|
return $thold_data['name_cache'];
|
|
}
|
|
|
|
function thold_str_replace($search, $replace, $subject) {
|
|
if (empty($replace) || $replace === 0) {
|
|
$replace = '';
|
|
}
|
|
|
|
return str_replace($search, $replace, $subject);
|
|
}
|
|
|
|
function thold_template_import($xml_data) {
|
|
global $config;
|
|
|
|
$debug_data = [];
|
|
|
|
if ($xml_data != '') {
|
|
// obtain debug information if it's set
|
|
$xml_array = xml2array($xml_data);
|
|
|
|
if (cacti_sizeof($xml_array)) {
|
|
foreach ($xml_array as $template => $contents) {
|
|
$error = false;
|
|
$save = [];
|
|
|
|
if (cacti_sizeof($contents)) {
|
|
foreach ($contents as $name => $value) {
|
|
switch($name) {
|
|
case 'data_template_id':
|
|
case 'data_template_hash':
|
|
// See if the hash exists, if it doesn't, Error Out
|
|
$found = db_fetch_cell_prepared('SELECT id
|
|
FROM data_template
|
|
WHERE hash = ?',
|
|
[$value]);
|
|
|
|
if (!empty($found)) {
|
|
$save['data_template_id'] = $found;
|
|
$save['data_template_hash'] = $value;
|
|
} else {
|
|
$error = true;
|
|
$debug_data['errors'][] = __('Threshold Template Subordinate Data Template Not Found!', 'thold');
|
|
}
|
|
|
|
break;
|
|
case 'data_source_id':
|
|
// See if the hash exists, if it doesn't, Error Out
|
|
$found = db_fetch_cell_prepared('SELECT id
|
|
FROM data_template_rrd
|
|
WHERE hash = ?',
|
|
[$value]);
|
|
|
|
if (!empty($found)) {
|
|
$save['data_source_id'] = $found;
|
|
} else {
|
|
$error = true;
|
|
$debug_data['errors'][] = __('Threshold Template Subordinate Data Source Not Found!', 'thold');
|
|
}
|
|
|
|
break;
|
|
case 'hash':
|
|
// See if the hash exists, if it does, update the thold
|
|
$found = db_fetch_cell_prepared('SELECT id
|
|
FROM thold_template
|
|
WHERE hash = ?',
|
|
[$value]);
|
|
|
|
if (!empty($found)) {
|
|
$save['hash'] = $value;
|
|
$save['id'] = $found;
|
|
} else {
|
|
$save['hash'] = $value;
|
|
$save['id'] = 0;
|
|
}
|
|
|
|
break;
|
|
case 'name':
|
|
$tname = $value;
|
|
$save['name'] = $value;
|
|
|
|
break;
|
|
default:
|
|
if (db_column_exists('thold_template', $name)) {
|
|
$save[$name] = $value;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!validate_template_import_columns($save)) {
|
|
$debug_data['errors'][] = __('Threshold Template import columns do not match the database schema', 'thold');
|
|
$error = true;
|
|
}
|
|
|
|
if (!$error) {
|
|
$id = sql_save($save, 'thold_template');
|
|
|
|
if ($id) {
|
|
if ($config['is_web']) {
|
|
$debug_data['success'][] = __esc('Threshold Template \'%s\' %s!', $tname, ($save['id'] > 0 ? __('Updated', 'thold') : __('Imported', 'thold')), 'thold');
|
|
} else {
|
|
$debug_data['success'][] = __('Threshold Template \'%s\' %s!', $tname, ($save['id'] > 0 ? __('Updated', 'thold') : __('Imported', 'thold')), 'thold');
|
|
}
|
|
} else {
|
|
if ($config['is_web']) {
|
|
$debug_data['failure'][] = __esc('Threshold Template \'%s\' %s Failed!', $tname, ($save['id'] > 0 ? __('Update', 'thold') : __('Import', 'thold')), 'thold');
|
|
} else {
|
|
$debug_data['failure'][] = __('Threshold Template \'%s\' %s Failed!', $tname, ($save['id'] > 0 ? __('Update', 'thold') : __('Import', 'thold')), 'thold');
|
|
}
|
|
}
|
|
} else {
|
|
$debug_data['failure'][] = __('Errors encountered while attempting to import Threshold Template data.', 'thold');
|
|
}
|
|
}
|
|
} else {
|
|
$debug_data['failure'][] = __('Threshold Template Import data was not found to be XML data.', 'thold');
|
|
}
|
|
} else {
|
|
$debug_data['failure'][] = __('Threshold Template Import data was not correct while importing Threshold Template.', 'thold');
|
|
}
|
|
|
|
return $debug_data;
|
|
}
|
|
|
|
function validate_template_import_columns($template) {
|
|
if (cacti_sizeof($template)) {
|
|
foreach ($template as $column => $data) {
|
|
if (!db_column_exists('thold_template', $column)) {
|
|
cacti_log('Template column \'' . $column . '\' is not valid for a threshold template.', false, 'THOLD');
|
|
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function thold_error_handler($errno, $errmsg, $filename, $linenum, $vars = []) {
|
|
if (read_config_option('log_verbosity') >= POLLER_VERBOSITY_DEBUG) {
|
|
// define all error types
|
|
$errortype = [
|
|
E_ERROR => 'Error',
|
|
E_WARNING => 'Warning',
|
|
E_PARSE => 'Parsing Error',
|
|
E_NOTICE => 'Notice',
|
|
E_CORE_ERROR => 'Core Error',
|
|
E_CORE_WARNING => 'Core Warning',
|
|
E_COMPILE_ERROR => 'Compile Error',
|
|
E_COMPILE_WARNING => 'Compile Warning',
|
|
E_USER_ERROR => 'User Error',
|
|
E_USER_WARNING => 'User Warning',
|
|
E_USER_NOTICE => 'User Notice',
|
|
E_STRICT => 'Runtime Notice'
|
|
];
|
|
|
|
if (defined('E_RECOVERABLE_ERROR')) {
|
|
$errortype[E_RECOVERABLE_ERROR] = 'Catchable Fatal Error';
|
|
}
|
|
|
|
if (defined('E_DEPRECATED')) {
|
|
$errortype[E_DEPRECATED] = 'Deprecated Warning';
|
|
}
|
|
|
|
// create an error string for the log
|
|
$err = "ERRNO:'" . $errno . "' TYPE:'" . $errortype[$errno] .
|
|
"' MESSAGE:'" . $errmsg . "' IN FILE:'" . $filename .
|
|
"' LINE NO:'" . $linenum . "'";
|
|
|
|
// let's ignore some lesser issues
|
|
if (substr_count($errmsg, 'date_default_timezone')) {
|
|
return;
|
|
}
|
|
|
|
if (substr_count($errmsg, 'Only variables')) {
|
|
return;
|
|
}
|
|
|
|
// log the error to the Cacti log
|
|
cacti_log('PROGERR: ' . $err, false, 'THOLD');
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* thold_get_rrd_statistics - given the local_data_id, the data source name, the interval and
|
|
* consolidation function. Return some statistics to the caller.
|
|
*
|
|
* @param $local_data_id - (int) The local_data_id of the data source
|
|
* @param $current_time - (int) The end time for the RRDtool call
|
|
* @param $prev_time - (int) The start time for the RRDtool call
|
|
* @param $avg_of_cf - (string) Get the Average of the chosen CF
|
|
*
|
|
* @return - (boolean|array) The value requested by the caller
|
|
*/
|
|
function thold_get_rrd_statistics($local_data_id, $current_time, $prev_time, $avg_of_cf) {
|
|
global $config;
|
|
|
|
$use_proxy = (read_config_option('storage_location') ? true : false);
|
|
|
|
$rrdfile = db_fetch_cell_prepared('SELECT rrd_path
|
|
FROM poller_item
|
|
WHERE local_data_id = ?',
|
|
[$local_data_id]);
|
|
|
|
if ($rrdfile == '') {
|
|
return false;
|
|
}
|
|
|
|
if ($use_proxy) {
|
|
$file_exists = rrdtool_execute("file_exists $rrdfile", true, RRDTOOL_OUTPUT_BOOLEAN, false, 'THOLD');
|
|
} else {
|
|
clearstatcache();
|
|
$file_exists = file_exists($rrdfile);
|
|
}
|
|
|
|
// don't attempt to get information if the file does not exist
|
|
if ($file_exists) {
|
|
$info = rrdtool_execute("info $rrdfile", false, RRDTOOL_OUTPUT_STDOUT, false, 'THOLD');
|
|
|
|
// don't do anything if RRDfile did not return data
|
|
if ($info != '') {
|
|
$info_array = explode("\n", $info);
|
|
|
|
$average = false;
|
|
$max = false;
|
|
$min = false;
|
|
$last = false;
|
|
$dsnames = [];
|
|
|
|
/* figure out what is in this RRDfile. Assume CF Uniformity as Cacti does not allow async rrdfiles.
|
|
* also verify the consolidation functions in the RRDfile for average and max calculations.
|
|
*/
|
|
if (cacti_sizeof($info_array)) {
|
|
foreach ($info_array as $line) {
|
|
if (substr_count($line, 'ds[')) {
|
|
$parts = explode(']', $line);
|
|
$parts2 = explode('[', $parts[0]);
|
|
|
|
$dsnames[trim($parts2[1])] = 1;
|
|
} elseif (substr_count($line, '.cf')) {
|
|
$parts = explode('=', $line);
|
|
|
|
if (substr_count($parts[1], 'AVERAGE')) {
|
|
$average = true;
|
|
} elseif (substr_count($parts[1], 'MAX')) {
|
|
$max = true;
|
|
} elseif (substr_count($parts[1], 'MIN')) {
|
|
$min = true;
|
|
} elseif (substr_count($parts[1], 'LAST')) {
|
|
$last = true;
|
|
}
|
|
} elseif (substr_count($line, 'step')) {
|
|
$parts = explode('=', $line);
|
|
|
|
$poller_interval = trim($parts[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// create the command syntax to get data
|
|
// assume that an RRDfile has not more than 62 data sources
|
|
$defs = 'abcdefghijklmnopqrstuvwxyz012345789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
$i = 0;
|
|
$j = 0;
|
|
$def = '';
|
|
$command = '';
|
|
$dsvalues = [];
|
|
|
|
// escape the file name if on Windows
|
|
if ($config['cacti_server_os'] != 'unix') {
|
|
$rrdfile = str_replace(':', '\\:', $rrdfile);
|
|
}
|
|
|
|
// setup the graph command by parsing through the internal data source names
|
|
if (cacti_sizeof($dsnames)) {
|
|
foreach ($dsnames as $dsname => $present) {
|
|
if ($average) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':AVERAGE ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_out=' . $defs[$j] . $defs[$i] . ',AVERAGE PRINT:' . $defs[$j] . $defs[$i] . '_out:%lf';
|
|
$i++;
|
|
}
|
|
|
|
if ($max) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':MAX ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_out=' . $defs[$j] . $defs[$i] . ',MAXIMUM PRINT:' . $defs[$j] . $defs[$i] . '_out:%lf';
|
|
$i++;
|
|
}
|
|
|
|
if ($min) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':MIN ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_out=' . $defs[$j] . $defs[$i] . ',MINIMUM PRINT:' . $defs[$j] . $defs[$i] . '_out:%lf';
|
|
$i++;
|
|
}
|
|
|
|
if ($last) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':LAST ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_out=' . $defs[$j] . $defs[$i] . ',LAST PRINT:' . $defs[$j] . $defs[$i] . '_out:%lf';
|
|
$i++;
|
|
}
|
|
|
|
if ($i > 50) {
|
|
$j++;
|
|
$i = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($avg_of_cf != '') {
|
|
switch($avg_of_cf) {
|
|
case 'MIN':
|
|
if ($min) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':MIN ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_cfa=' . $defs[$j] . $defs[$i] . ',AVERAGE PRINT:' . $defs[$j] . $defs[$i] . '_cfa:%lf';
|
|
$i++;
|
|
}
|
|
|
|
break;
|
|
case 'MAX':
|
|
if ($max) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':MAX ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_cfa=' . $defs[$j] . $defs[$i] . ',AVERAGE PRINT:' . $defs[$j] . $defs[$i] . '_cfa:%lf';
|
|
$i++;
|
|
}
|
|
|
|
break;
|
|
case 'AVG':
|
|
if ($average) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':AVERAGE ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_cfa=' . $defs[$j] . $defs[$i] . ',AVERAGE PRINT:' . $defs[$j] . $defs[$i] . '_cfa:%lf';
|
|
$i++;
|
|
}
|
|
|
|
break;
|
|
case 'LAST':
|
|
if ($last) {
|
|
$def .= 'DEF:' . $defs[$j] . $defs[$i] . '="' . $rrdfile . '":' . $dsname . ':LAST ';
|
|
$command .= ' VDEF:' . $defs[$j] . $defs[$i] . '_cfa=' . $defs[$j] . $defs[$i] . ',AVERAGE PRINT:' . $defs[$j] . $defs[$i] . '_cfa:%lf';
|
|
$i++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// now execute the graph command
|
|
$stats_cmd = 'graph x --start ' . $prev_time . ' --end ' . $current_time . ' ' . trim($def) . ' ' . trim($command);
|
|
|
|
// uncomment for diagnostics
|
|
// cacti_log($stats_cmd, false, 'THOLD');
|
|
|
|
$xport_data = rrdtool_execute($stats_cmd, false, RRDTOOL_OUTPUT_STDOUT, false, 'THOLD');
|
|
|
|
$position = [];
|
|
$position[] = ['RETURN' => 'RETURN'];
|
|
|
|
// initialize the array of return values
|
|
foreach ($dsnames as $dsname => $present) {
|
|
$dsvalues[$dsname]['AVG'] = 0;
|
|
$dsvalues[$dsname]['MAX'] = 0;
|
|
$dsvalues[$dsname]['MIN'] = 0;
|
|
$dsvalues[$dsname]['LAST'] = 0;
|
|
|
|
if ($avg_of_cf != '') {
|
|
$dsvalues[$dsname]['CFA'] = 0;
|
|
}
|
|
|
|
if ($average) {
|
|
$position[] = [$dsname => 'AVG'];
|
|
}
|
|
|
|
if ($max) {
|
|
$position[] = [$dsname => 'MAX'];
|
|
}
|
|
|
|
if ($min) {
|
|
$position[] = [$dsname => 'MIN'];
|
|
}
|
|
|
|
if ($last) {
|
|
$position[] = [$dsname => 'LAST'];
|
|
}
|
|
|
|
if ($avg_of_cf != '') {
|
|
$position[] = [$dsname => 'CFA'];
|
|
}
|
|
}
|
|
|
|
// process the xport array and return average and peak values
|
|
if ($xport_data != '') {
|
|
$xport_array = explode("\n", $xport_data);
|
|
// print_r($xport_array);
|
|
|
|
if (cacti_sizeof($xport_array)) {
|
|
foreach ($xport_array as $index => $line) {
|
|
if ($line == '') {
|
|
continue;
|
|
}
|
|
|
|
if ($index > 0) {
|
|
// Catch the last line
|
|
if (substr($line, 0, 2) == 'OK') {
|
|
$line = trim($line, ' OK');
|
|
$parts = explode(' ', $line);
|
|
// print $line . PHP_EOL;
|
|
|
|
foreach ($parts as $line) {
|
|
$sparts = explode(':', $line);
|
|
|
|
switch($sparts[0]) {
|
|
case 'u':
|
|
$user_time = $sparts[1];
|
|
|
|
break;
|
|
case 's':
|
|
$system_time = $sparts[1];
|
|
|
|
break;
|
|
case 'r':
|
|
$real_time = $sparts[1];
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
} else {
|
|
foreach ($position[$index] as $dsname => $stat) {
|
|
$dsvalues[$dsname][$stat] = trim($line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $dsvalues;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|