Files
Cactiplugin_thold/thold_functions.php
T

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 &nbsp;
$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>&nbsp;' . round($end_time - $start_time,2) . ' seconds, ';
print '<b>' . __('User:', 'thold') . '</b>&nbsp;' . round($utime,2) . ' seconds, ';
print '<b>' . __('System:', 'thold') . '</b>&nbsp;' . round($stime,2) . ' seconds, ';
print '<b>' . __('Swaps:', 'thold') . '</b>&nbsp;' . ($swaps) . ' swaps, ';
print '<b>' . __('Pages:', 'thold') . '</b>&nbsp;' . ($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 = ' &#181;';
$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 .= "&nbsp;<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;
}