mirror of
https://github.com/Cacti/plugin_thold.git
synced 2026-10-23 03:27:05 +09:00
886 lines
35 KiB
PHP
886 lines
35 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/ |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
function thold_poller_bottom() {
|
|
global $config, $database_type, $database_default, $database_hostname;
|
|
global $database_username, $database_password, $database_port, $database_ssl;
|
|
|
|
$command_string = cacti_escapeshellcmd(read_config_option('path_php_binary'));
|
|
$file_path = $config['base_path'] . '/plugins/thold/poller_thold.php';
|
|
|
|
if (file_exists($file_path)) {
|
|
exec_background($command_string, $file_path);
|
|
} else {
|
|
cacti_log('FATAL: The Threshold Processing Script \'poller_thold.php\' is missing', false, 'THOLD');
|
|
}
|
|
}
|
|
|
|
function thold_cleanup_log() {
|
|
$daysToStoreLogs = read_config_option('thold_log_storage');
|
|
|
|
if (empty($daysToStoreLogs)) {
|
|
$daysToStoreLogs = 31;
|
|
set_config_option('thold_log_storage', '31');
|
|
}
|
|
|
|
$t = time() - (86400 * $daysToStoreLogs); // Delete Logs over a month old
|
|
|
|
db_execute_prepared('DELETE FROM plugin_thold_log
|
|
WHERE time < ?',
|
|
[$t]);
|
|
|
|
if (db_affected_rows() > 0) {
|
|
set_config_option('time_last_change_thold_log', time());
|
|
}
|
|
}
|
|
|
|
function thold_poller_output(&$rrd_update_array) {
|
|
global $config, $debug;
|
|
|
|
include_once($config['base_path'] . '/plugins/thold/thold_functions.php');
|
|
include_once($config['library_path'] . '/snmp.php');
|
|
|
|
$rrd_reindexed = [];
|
|
$rrd_time_reindexed = [];
|
|
$local_data_ids = '';
|
|
|
|
foreach ($rrd_update_array as $item) {
|
|
if (isset($item['times'][key($item['times'])])) {
|
|
$local_data_ids .= ($local_data_ids != '' ? ', ' : '') . $item['local_data_id'];
|
|
$rrd_reindexed[$item['local_data_id']] = $item['times'][key($item['times'])];
|
|
$rrd_time_reindexed[$item['local_data_id']] = key($item['times']);
|
|
}
|
|
}
|
|
|
|
if ($local_data_ids != '') {
|
|
if (read_config_option('thold_daemon_enable') == 'on') {
|
|
$chunks = ceil(sizeof($rrd_update_array) / 50);
|
|
|
|
if ($chunks < 1) {
|
|
$chunks = 1;
|
|
}
|
|
|
|
$rrd_update_array_chunks = array_chunk($rrd_update_array, $chunks, true);
|
|
|
|
foreach ($rrd_update_array_chunks as $rrd_update_array_chunk) {
|
|
$rrd_reindexed = [];
|
|
$rrd_time_reindexed = [];
|
|
$local_data_ids = '';
|
|
$thold_items = [];
|
|
|
|
foreach ($rrd_update_array_chunk as $item) {
|
|
if (isset($item['times'][key($item['times'])])) {
|
|
$local_data_ids .= ($local_data_ids != '' ? ', ' : '') . $item['local_data_id'];
|
|
|
|
$rrd_reindexed[$item['local_data_id']] = $item['times'][key($item['times'])];
|
|
$rrd_time_reindexed[$item['local_data_id']] = key($item['times']);
|
|
}
|
|
}
|
|
|
|
if ($local_data_ids != '') {
|
|
$thold_items = db_fetch_assoc("SELECT id, local_data_id, thread_id
|
|
FROM thold_data
|
|
WHERE thold_data.local_data_id IN ($local_data_ids)");
|
|
}
|
|
|
|
if (cacti_sizeof($thold_items)) {
|
|
/**
|
|
* cache required polling data. prefer bulk inserts for
|
|
* performance reasons - start with chunks of 1000 items
|
|
*/
|
|
$sql_max_inserts = 1000;
|
|
$thold_items = array_chunk($thold_items, $sql_max_inserts);
|
|
|
|
$sql_insert = 'INSERT INTO plugin_thold_daemon_data
|
|
(poller_id, id, thread_id, rrd_reindexed, rrd_time_reindexed) VALUES ';
|
|
|
|
foreach ($thold_items as $packet) {
|
|
$sql_values = '';
|
|
|
|
foreach ($packet as $thold_item) {
|
|
$sql_values .= ($sql_values != '' ? ', ' : '') . '(' . $config['poller_id'] . ', ' . $thold_item['id'] . ', ' . $thold_item['thread_id'] . ', ' . db_qstr(json_encode($rrd_reindexed[$thold_item['local_data_id']])) . ', ' . $rrd_time_reindexed[$thold_item['local_data_id']] . ')';
|
|
}
|
|
|
|
db_execute($sql_insert . $sql_values);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $rrd_update_array;
|
|
}
|
|
} else {
|
|
return $rrd_update_array;
|
|
}
|
|
|
|
$tholds = db_fetch_assoc("SELECT td.id, td.name_cache AS thold_name,
|
|
td.local_graph_id, td.percent_ds, td.expression, td.upper_ds, td.data_type,
|
|
td.cdef, td.local_data_id, td.data_template_rrd_id, td.lastread,
|
|
UNIX_TIMESTAMP(td.lasttime) AS lasttime, td.oldvalue,
|
|
td.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 IN($local_data_ids)");
|
|
|
|
if (cacti_sizeof($tholds)) {
|
|
$sql = [];
|
|
|
|
foreach ($tholds as $thold_data) {
|
|
thold_debug("Checking Threshold: Name: '" . $thold_data['thold_name'] . "', Graph: '" . $thold_data['local_graph_id'] . "'");
|
|
|
|
$item = [];
|
|
$currenttime = 0;
|
|
$postvalue = thold_get_currentval($thold_data, $rrd_reindexed, $rrd_time_reindexed, $item, $currenttime);
|
|
$currentval = $postvalue;
|
|
|
|
switch ($thold_data['data_type']) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
if ($thold_data['cdef'] != 0) {
|
|
$currentval = thold_build_cdef($thold_data['cdef'], $postvalue, $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
|
|
}
|
|
|
|
break;
|
|
case 2:
|
|
if ($thold_data['percent_ds'] != '') {
|
|
$currentval = thold_calculate_percent($thold_data, $postvalue, $rrd_reindexed);
|
|
}
|
|
|
|
break;
|
|
case 3:
|
|
if ($thold_data['expression'] != '') {
|
|
$currentval = thold_calculate_expression($thold_data, $postvalue, $rrd_reindexed, $rrd_time_reindexed);
|
|
}
|
|
|
|
break;
|
|
case 4:
|
|
if ($thold_data['upper_ds'] != '') {
|
|
$currentval = thold_calculate_lower_upper($thold_data, $postvalue, $rrd_reindexed);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (!is_numeric($currentval)) {
|
|
if (read_config_option('thold_consider_unknown_zero') == 'on') {
|
|
$currentval = strtolower($currentval);
|
|
|
|
if ($currentval == 'u' || $currentval == 'nan' || $currentval == '') {
|
|
$currentval = 0;
|
|
thold_debug('Threshold: ' . $thold_data['thold_name'] . ' changing unknown value to zero', 'thold');
|
|
|
|
if (read_config_option('thold_log_unknown_to_zero') == 'on') {
|
|
cacti_log('NOTE: Threshold \'' . $thold_data['thold_name'] . '\' changing unknown value to zero', true, 'THOLD');
|
|
}
|
|
} else {
|
|
$currentval = '';
|
|
}
|
|
} else {
|
|
$currentval = '';
|
|
}
|
|
}
|
|
|
|
// This stores the raw value into the data source and is important for
|
|
// Counters, where calculating the difference is important.
|
|
// The unset case is problematic and may lead to false triggering
|
|
// events. So, in those cases, we will store the 'oldvalue'.
|
|
if (isset($item[$thold_data['name']])) {
|
|
$rawvalue = $item[$thold_data['name']];
|
|
} else {
|
|
$rawvalue = $thold_data['oldvalue'];
|
|
}
|
|
|
|
$sql[] = '(' . $thold_data['id'] . ', 1, ' . db_qstr($currentval) . ', FROM_UNIXTIME(' . $currenttime . '), ' . db_qstr($rawvalue) . ')';
|
|
}
|
|
|
|
if (cacti_sizeof($sql)) {
|
|
$chunks = array_chunk($sql, 400);
|
|
|
|
foreach ($chunks as $c) {
|
|
db_execute('INSERT INTO thold_data
|
|
(id, tcheck, lastread, lasttime, oldvalue)
|
|
VALUES ' . implode(', ', $c) . '
|
|
ON DUPLICATE KEY UPDATE
|
|
tcheck = VALUES(tcheck),
|
|
lastread = VALUES(lastread),
|
|
lasttime = VALUES(lasttime),
|
|
oldvalue = VALUES(oldvalue)');
|
|
}
|
|
|
|
// accommodate deleted tholds
|
|
db_execute('DELETE FROM thold_data WHERE local_data_id = 0');
|
|
|
|
if (db_affected_rows() > 0) {
|
|
set_config_option('time_last_change_thold', time());
|
|
}
|
|
}
|
|
}
|
|
|
|
return $rrd_update_array;
|
|
}
|
|
|
|
if (!function_exists('array_column')) {
|
|
function array_column($array, $column_name) {
|
|
return array_map(function ($element) use ($column_name) {
|
|
return $element[$column_name];
|
|
}, $array);
|
|
}
|
|
}
|
|
|
|
function thold_check_all_thresholds() {
|
|
global $config;
|
|
|
|
include($config['base_path'] . '/plugins/thold/includes/arrays.php');
|
|
include_once($config['base_path'] . '/plugins/thold/thold_functions.php');
|
|
include_once($config['base_path'] . '/lib/time.php');
|
|
|
|
if (read_config_option('remote_storage_method') == 1) {
|
|
if ($config['poller_id'] == 1) {
|
|
$sql_query = "SELECT td.*, h.hostname,
|
|
h.description, h.site_id, h.location, h.notes AS dnotes, h.snmp_engine_id
|
|
FROM thold_data AS td
|
|
LEFT JOIN host AS h
|
|
ON h.id = td.host_id
|
|
LEFT JOIN data_template_rrd AS dtr
|
|
ON dtr.id = td.data_template_rrd_id
|
|
WHERE thold_per_enabled = 'on'
|
|
AND (
|
|
thold_template_id = 0
|
|
OR (
|
|
thold_template_id > 0
|
|
AND (
|
|
template_enabled != 'on' OR (template_enabled = 'on' AND thold_enabled = 'on')
|
|
)
|
|
)
|
|
)
|
|
AND h.poller_id = 1 OR h.poller_id IS NULL
|
|
AND td.tcheck = 1
|
|
AND h.status = 3";
|
|
} else {
|
|
$sql_query = 'SELECT td.*, h.hostname,
|
|
h.description, h.site_id, h.location, h.notes AS dnotes, h.snmp_engine_id
|
|
FROM thold_data AS td
|
|
LEFT JOIN host AS h
|
|
ON h.id = td.host_id
|
|
LEFT JOIN data_template_rrd AS dtr
|
|
ON dtr.id = td.data_template_rrd_id
|
|
WHERE h.poller_id = ' . $config['poller_id'] . "
|
|
AND thold_per_enabled = 'on'
|
|
AND (
|
|
thold_template_id = 0
|
|
OR (
|
|
thold_template_id > 0
|
|
AND (
|
|
template_enabled != 'on' OR (template_enabled = 'on' AND thold_enabled = 'on')
|
|
)
|
|
)
|
|
)
|
|
AND td.tcheck = 1
|
|
AND h.status = 3";
|
|
}
|
|
} else {
|
|
$sql_query = "SELECT td.*, h.hostname,
|
|
h.description, h.site_id, h.location, h.notes AS dnotes, h.snmp_engine_id
|
|
FROM thold_data AS td
|
|
LEFT JOIN data_template_rrd AS dtr
|
|
ON dtr.id = td.data_template_rrd_id
|
|
LEFT JOIN host as h
|
|
ON td.host_id = h.id
|
|
WHERE thold_per_enabled = 'on'
|
|
AND (
|
|
thold_template_id = 0
|
|
OR (
|
|
thold_template_id > 0
|
|
AND (
|
|
template_enabled != 'on' OR (template_enabled = 'on' AND thold_enabled = 'on')
|
|
)
|
|
)
|
|
)
|
|
AND td.tcheck = 1
|
|
AND h.status = 3";
|
|
}
|
|
|
|
$tholds = api_plugin_hook_function('thold_get_live_hosts', db_fetch_assoc($sql_query));
|
|
|
|
$total_tholds = sizeof($tholds);
|
|
|
|
foreach ($tholds as $thold) {
|
|
thold_check_threshold($thold);
|
|
}
|
|
|
|
if (read_config_option('remote_storage_method') == 1) {
|
|
if ($config['poller_id'] == 1) {
|
|
db_execute('UPDATE thold_data AS td
|
|
LEFT JOIN host AS h
|
|
ON td.host_id = h.id
|
|
SET tcheck = 0
|
|
WHERE h.poller_id = 1
|
|
OR h.poller_id IS NULL');
|
|
} else {
|
|
db_execute_prepared('UPDATE thold_data AS td
|
|
INNER JOIN host AS h
|
|
ON td.host_id = h.id
|
|
SET td.tcheck = 0
|
|
WHERE h.poller_id = ?',
|
|
[$config['poller_id']]);
|
|
}
|
|
} else {
|
|
db_execute('UPDATE thold_data AS td SET td.tcheck = 0');
|
|
}
|
|
|
|
return $total_tholds;
|
|
}
|
|
|
|
function thold_update_host_status() {
|
|
global $config;
|
|
|
|
// Return if we aren't set to notify
|
|
$deadnotify = (read_config_option('alert_deadnotify') == 'on');
|
|
|
|
if (!$deadnotify) {
|
|
return 0;
|
|
}
|
|
|
|
include_once($config['base_path'] . '/plugins/thold/thold_functions.php');
|
|
include_once($config['library_path'] . '/snmp.php');
|
|
|
|
if (api_plugin_is_enabled('maint')) {
|
|
include_once($config['base_path'] . '/plugins/maint/functions.php');
|
|
}
|
|
|
|
$ping_failure_count = read_config_option('ping_failure_count');
|
|
|
|
$queue = read_config_option('thold_notification_queue');
|
|
|
|
// Lets find hosts that were down, but are now back up
|
|
if (read_config_option('remote_storage_method') == 1) {
|
|
$failed = db_fetch_assoc_prepared('SELECT *
|
|
FROM plugin_thold_host_failed
|
|
WHERE poller_id = ?',
|
|
[$config['poller_id']]);
|
|
} else {
|
|
$failed = db_fetch_assoc('SELECT *
|
|
FROM plugin_thold_host_failed');
|
|
}
|
|
|
|
if (cacti_sizeof($failed)) {
|
|
foreach ($failed as $fh) {
|
|
$alert_email = read_config_option('alert_email');
|
|
|
|
$host = db_fetch_row_prepared('SELECT *
|
|
FROM host
|
|
WHERE id = ?',
|
|
[$fh['host_id']]);
|
|
|
|
$notify_list_id = 0;
|
|
|
|
if (!sizeof($host)) {
|
|
db_execute_prepared('DELETE
|
|
FROM plugin_thold_host_failed
|
|
WHERE host_id = ?',
|
|
[$fh['host_id']]);
|
|
|
|
set_config_option('time_last_change_thold_device', time());
|
|
} elseif ($host['status'] == HOST_UP) {
|
|
$snmp_system = '';
|
|
$snmp_hostname = '';
|
|
$snmp_location = '';
|
|
$snmp_contact = '';
|
|
$snmp_uptime = '';
|
|
$uptimelong = '';
|
|
$downtimemsg = '';
|
|
|
|
if (($host['snmp_community'] == '' && $host['snmp_username'] == '') || $host['snmp_version'] == 0) {
|
|
// SNMP not in use
|
|
$snmp_system = __('SNMP not in use', 'thold');
|
|
} else {
|
|
$snmp_system = cacti_snmp_get($host['hostname'], $host['snmp_community'], '.1.3.6.1.2.1.1.1.0', $host['snmp_version'], $host['snmp_username'], $host['snmp_password'], $host['snmp_auth_protocol'], $host['snmp_priv_passphrase'], $host['snmp_priv_protocol'], $host['snmp_context'], $host['snmp_port'], $host['snmp_timeout'], read_config_option('snmp_retries'), SNMP_WEBUI);
|
|
|
|
if (substr_count($snmp_system, '00:')) {
|
|
$snmp_system = str_replace('00:', '', $snmp_system);
|
|
$snmp_system = str_replace(':', ' ', $snmp_system);
|
|
}
|
|
|
|
if ($snmp_system != '') {
|
|
$snmp_uptime = cacti_snmp_get($host['hostname'], $host['snmp_community'], '.1.3.6.1.6.3.10.2.1.3.0', $host['snmp_version'], $host['snmp_username'], $host['snmp_password'], $host['snmp_auth_protocol'], $host['snmp_priv_passphrase'], $host['snmp_priv_protocol'], $host['snmp_context'], $host['snmp_port'], $host['snmp_timeout'], read_config_option('snmp_retries'), SNMP_WEBUI);
|
|
|
|
if (!is_numeric($snmp_uptime)) {
|
|
$snmp_uptime = cacti_snmp_get($host['hostname'], $host['snmp_community'], '.1.3.6.1.2.1.1.3.0', $host['snmp_version'], $host['snmp_username'], $host['snmp_password'], $host['snmp_auth_protocol'], $host['snmp_priv_passphrase'], $host['snmp_priv_protocol'], $host['snmp_context'], $host['snmp_port'], $host['snmp_timeout'], read_config_option('snmp_retries'), SNMP_WEBUI);
|
|
} else {
|
|
$snmp_uptime *= 100;
|
|
}
|
|
|
|
$snmp_hostname = cacti_snmp_get($host['hostname'], $host['snmp_community'], '.1.3.6.1.2.1.1.5.0', $host['snmp_version'], $host['snmp_username'], $host['snmp_password'], $host['snmp_auth_protocol'], $host['snmp_priv_passphrase'], $host['snmp_priv_protocol'], $host['snmp_context'], $host['snmp_port'], $host['snmp_timeout'], read_config_option('snmp_retries'), SNMP_WEBUI);
|
|
|
|
$snmp_location = cacti_snmp_get($host['hostname'], $host['snmp_community'], '.1.3.6.1.2.1.1.6.0', $host['snmp_version'], $host['snmp_username'], $host['snmp_password'], $host['snmp_auth_protocol'], $host['snmp_priv_passphrase'], $host['snmp_priv_protocol'], $host['snmp_context'], $host['snmp_port'], $host['snmp_timeout'], read_config_option('snmp_retries'), SNMP_WEBUI);
|
|
|
|
$snmp_contact = cacti_snmp_get($host['hostname'], $host['snmp_community'], '.1.3.6.1.2.1.1.4.0', $host['snmp_version'], $host['snmp_username'], $host['snmp_password'], $host['snmp_auth_protocol'], $host['snmp_priv_passphrase'], $host['snmp_priv_protocol'], $host['snmp_context'], $host['snmp_port'], $host['snmp_timeout'], read_config_option('snmp_retries'), SNMP_WEBUI);
|
|
|
|
if (is_numeric($snmp_uptime)) {
|
|
$days = intval($snmp_uptime / (60 * 60 * 24 * 100));
|
|
$remainder = $snmp_uptime % (60 * 60 * 24 * 100);
|
|
$hours = intval($remainder / (60 * 60 * 100));
|
|
$remainder = $remainder % (60 * 60 * 100);
|
|
$minutes = intval($remainder / (60 * 100));
|
|
$uptimelong = $days . 'd ' . $hours . 'h ' . $minutes . 'm';
|
|
} else {
|
|
$days = '0';
|
|
$remainder = '0';
|
|
$hours = '0';
|
|
$remainder = '0';
|
|
$minutes = '0';
|
|
$uptimelong = $days . 'd ' . $hours . 'h ' . $minutes . 'm';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strtotime($host['status_fail_date']) > 192800) {
|
|
$downtime = time() - strtotime($host['status_fail_date']);
|
|
$downtime_days = floor($downtime / 86400);
|
|
$downtime_hours = floor(($downtime - ($downtime_days * 86400)) / 3600);
|
|
$downtime_minutes = floor(($downtime - ($downtime_days * 86400) - ($downtime_hours * 3600)) / 60);
|
|
$downtime_seconds = $downtime - ($downtime_days * 86400) - ($downtime_hours * 3600) - ($downtime_minutes * 60);
|
|
|
|
if ($downtime_days > 0) {
|
|
$downtimemsg = $downtime_days . 'd ' . $downtime_hours . 'h ' . $downtime_minutes . 'm ' . $downtime_seconds . 's ';
|
|
} elseif ($downtime_hours > 0) {
|
|
$downtimemsg = $downtime_hours . 'h ' . $downtime_minutes . 'm ' . $downtime_seconds . 's';
|
|
} elseif ($downtime_minutes > 0) {
|
|
$downtimemsg = $downtime_minutes . 'm ' . $downtime_seconds . 's';
|
|
} else {
|
|
$downtimemsg = $downtime_seconds . 's ';
|
|
}
|
|
} else {
|
|
$downtimemsg = __('N/A', 'thold');
|
|
}
|
|
|
|
$subject = read_config_option('thold_up_subject');
|
|
|
|
if ($subject == '') {
|
|
$subject = __('Devices Notice: <DESCRIPTION> (<HOSTNAME>) returned from DOWN state', 'thold');
|
|
}
|
|
|
|
$site = db_fetch_cell_prepared('SELECT name FROM sites WHERE id = ?', [$host['site_id']]);
|
|
|
|
if ($site == '') {
|
|
$site = 'Unspecified';
|
|
}
|
|
|
|
$subject = thold_str_replace('<HOSTNAME>', $host['hostname'], $subject);
|
|
$subject = thold_str_replace('<DESCRIPTION>', $host['description'], $subject);
|
|
$subject = thold_str_replace('<SITE>', $site, $subject);
|
|
$subject = thold_str_replace('<LOCATION>', $host['location'], $subject);
|
|
$subject = thold_str_replace('<DOWN/UP>', 'UP', $subject);
|
|
$subject = thold_str_replace('<DOWNTIME>', $downtimemsg, $subject);
|
|
$subject = thold_str_replace('<NOTES>', $host['notes'], $subject);
|
|
$subject = strip_tags($subject);
|
|
|
|
$msg = read_config_option('thold_up_text');
|
|
|
|
if ($msg == '') {
|
|
$msg = __('<br>System <DESCRIPTION> (<HOSTNAME>) status: <DOWN/UP><br><br>Site: <SITE><br>Location: <LOCATION><br>Current ping response: <CUR_TIME> ms<br>Average system response : <AVG_TIME> ms<br>System availability: <AVAILABILITY><br>Total Checks Since Clear: <TOT_POLL><br>Total Failed Checks: <FAIL_POLL><br>Last Date Checked UP: <LAST_FAIL><br>Devices Previously DOWN for: <DOWNTIME><br><br>SNMP Info:<br>Name - <SNMP_HOSTNAME><br>Location - <SNMP_LOCATION><br>Uptime - <UPTIMETEXT> (<UPTIME> ms)<br>System - <SNMP_SYSTEM><br><br>NOTE: <NOTES>', 'thold');
|
|
}
|
|
|
|
$msg = thold_str_replace('<SUBJECT>', $subject, $msg);
|
|
$msg = thold_str_replace('<HOSTNAME>', $host['hostname'], $msg);
|
|
$msg = thold_str_replace('<HOST_ID>', $host['id'], $msg);
|
|
$msg = thold_str_replace('<DESCRIPTION>', $host['description'], $msg);
|
|
$msg = thold_str_replace('<SITE>', $site, $msg);
|
|
$msg = thold_str_replace('<LOCATION>', $host['location'], $msg);
|
|
$msg = thold_str_replace('<UPTIME>', $snmp_uptime, $msg);
|
|
$msg = thold_str_replace('<UPTIMETEXT>', $uptimelong, $msg);
|
|
|
|
$msg = thold_str_replace('<TIME>', time(), $msg);
|
|
$msg = thold_str_replace('<DATE>', date(CACTI_DATE_TIME_FORMAT), $msg);
|
|
$msg = thold_str_replace('<DATE_RFC822>', date(DATE_RFC822), $msg);
|
|
|
|
$msg = thold_str_replace('<DOWNTIME>', $downtimemsg, $msg);
|
|
$msg = thold_str_replace('<MESSAGE>', '', $msg);
|
|
$msg = thold_str_replace('<DOWN/UP>', 'UP', $msg);
|
|
|
|
$msg = thold_str_replace('<SNMP_HOSTNAME>', $snmp_hostname, $msg);
|
|
$msg = thold_str_replace('<SNMP_LOCATION>', $snmp_location, $msg);
|
|
$msg = thold_str_replace('<SNMP_CONTACT>', $snmp_contact, $msg);
|
|
$msg = thold_str_replace('<SNMP_SYSTEM>', html_split_string($snmp_system), $msg);
|
|
$msg = thold_str_replace('<LAST_FAIL>', $host['status_fail_date'], $msg);
|
|
$msg = thold_str_replace('<AVAILABILITY>', number_format_i18n(($host['availability']), 2) . ' %', $msg);
|
|
$msg = thold_str_replace('<TOT_POLL>', number_format_i18n($host['total_polls']), $msg);
|
|
$msg = thold_str_replace('<FAIL_POLL>', number_format_i18n($host['failed_polls']), $msg);
|
|
$msg = thold_str_replace('<CUR_TIME>', number_format_i18n(($host['cur_time']), 2), $msg);
|
|
$msg = thold_str_replace('<AVG_TIME>', number_format_i18n(($host['avg_time']), 2), $msg);
|
|
$msg = thold_str_replace('<NOTES>', $host['notes'], $msg);
|
|
$msg = thold_str_replace("\n", '<br>', $msg);
|
|
|
|
if (api_plugin_is_enabled('maint') && plugin_maint_check_cacti_host($host['id'])) {
|
|
cacti_log('WARNING: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] is recovering! Only logging, maint device', true, 'THOLD');
|
|
} else {
|
|
switch ($host['thold_send_email']) {
|
|
case '0': // Disabled
|
|
$alert_email = '';
|
|
|
|
break;
|
|
case '1': // Global List
|
|
break;
|
|
case '2': // Devices List Only
|
|
$alert_email = get_thold_notification_emails($host['thold_host_email']);
|
|
$notify_list_id = $host['thold_host_email'];
|
|
|
|
break;
|
|
case '3': // Global and Devices List
|
|
$alert_email = $alert_email . ',' . get_thold_notification_emails($host['thold_host_email']);
|
|
$notify_list_id = $host['thold_host_email'];
|
|
|
|
break;
|
|
}
|
|
|
|
api_plugin_hook_function(
|
|
'thold_device_recovering',
|
|
[
|
|
'device' => $host,
|
|
'subject' => $subject,
|
|
'message' => $msg,
|
|
'email' => $alert_email
|
|
]
|
|
);
|
|
|
|
cacti_log('WARNING: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] is recovering!', true, 'THOLD');
|
|
|
|
if ($alert_email == '' && $host['thold_send_email'] > 0) {
|
|
cacti_log('WARNING: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] can not send a Device recovering email for \'' . $host['description'] . '\' since the \'Alert Email\' setting is not set for Device!', true, 'THOLD');
|
|
} elseif ($host['thold_send_email'] == '0') {
|
|
cacti_log('NOTE: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] did not send a Device recovering email for \'' . $host['description'] . '\', disabled per Device setting!', true, 'THOLD');
|
|
} elseif ($alert_email != '') {
|
|
thold_mail($alert_email, '', '', $subject, $msg, '', '', $notify_list_id, $host, '', 7, 'thold_uhost_mail');
|
|
}
|
|
|
|
$command = read_config_option('thold_device_command');
|
|
|
|
if ($command != '') {
|
|
thold_putenv('THOLD_SUBJECT=' . $subject, true);
|
|
thold_putenv('THOLD_HOSTNAME=' . $host['hostname']);
|
|
thold_putenv('THOLD_HOST_ID=' . $host['id']);
|
|
thold_putenv('THOLD_DESCRIPTION=' . $host['description']);
|
|
thold_putenv('THOLD_SITE=' . $site);
|
|
thold_putenv('THOLD_LOCATION=' . $host['location']);
|
|
thold_putenv('THOLD_TIME=' . time());
|
|
thold_putenv('THOLD_DATE=' . date(CACTI_DATE_TIME_FORMAT));
|
|
thold_putenv('THOLD_DATE_RFC822=' . date(DATE_RFC822));
|
|
|
|
thold_putenv('THOLD_UPTIME=' . $snmp_uptime);
|
|
thold_putenv('THOLD_UPTIMETEXT=' . $uptimelong);
|
|
thold_putenv('THOLD_DOWNTIME=' . $downtimemsg);
|
|
thold_putenv('THOLD_MESSAGE=' . '');
|
|
thold_putenv('THOLD_DOWNUP=' . 'UP');
|
|
|
|
thold_putenv('THOLD_SNMP_HOSTNAME=' . $snmp_hostname);
|
|
thold_putenv('THOLD_SNMP_LOCATION=' . $snmp_location);
|
|
thold_putenv('THOLD_SNMP_CONTACT=' . $snmp_contact);
|
|
thold_putenv('THOLD_SNMP_SYSTEM=' . $snmp_system);
|
|
thold_putenv('THOLD_LAST_FAIL=' . $host['status_fail_date']);
|
|
thold_putenv('THOLD_AVAILABILITY=' . $host['availability']);
|
|
thold_putenv('THOLD_TOT_POLL=' . $host['total_polls']);
|
|
thold_putenv('THOLD_FAIL_POLL=' . $host['failed_polls']);
|
|
thold_putenv('THOLD_CUR_TIME=' . $host['cur_time']);
|
|
thold_putenv('THOLD_AVG_TIME=' . $host['avg_time']);
|
|
$environment = thold_putenv('THOLD_NOTES=' . $host['notes']);
|
|
|
|
if (file_exists($command) && is_executable($command)) {
|
|
$output = [];
|
|
$return = 0;
|
|
|
|
if ($queue == '') {
|
|
exec($command, $output, $return);
|
|
|
|
cacti_log('Device Up Command for Device[' . $host['id'] . '] Command[' . $command . '] ExitStatus[' . $return . '] Output[' . implode(' ', $output) . ']', false, 'THOLD');
|
|
} else {
|
|
$data = [
|
|
'command' => $command,
|
|
'data' => $host,
|
|
'environment' => $environment
|
|
];
|
|
|
|
thold_notification_add('thold_uhost_cmd', $data, 'id', $notify_list_id, $host);
|
|
}
|
|
} else {
|
|
cacti_log('WARNING: Device Up Command for Device[' . $host['id'] . '] Command[' . $command . '] Is either Not found or Not executable!', false, 'THOLD');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Lets find hosts that are down
|
|
if (read_config_option('remote_storage_method') == 1) {
|
|
$hosts = db_fetch_assoc_prepared('SELECT *
|
|
FROM host
|
|
WHERE disabled = ""
|
|
AND availability_method > 0
|
|
AND status = ?
|
|
AND status_event_count = IF(thold_failure_count > 0, thold_failure_count, ?)
|
|
AND poller_id = ?',
|
|
[HOST_DOWN, $ping_failure_count, $config['poller_id']]);
|
|
} else {
|
|
$hosts = db_fetch_assoc_prepared('SELECT *
|
|
FROM host
|
|
WHERE disabled = ""
|
|
AND availability_method > 0
|
|
AND status = ?
|
|
AND status_event_count = IF(thold_failure_count > 0, thold_failure_count, ?)',
|
|
[HOST_DOWN, $ping_failure_count]);
|
|
}
|
|
|
|
$total_hosts = cacti_sizeof($hosts);
|
|
|
|
if ($total_hosts) {
|
|
foreach ($hosts as $host) {
|
|
$notify_list_id = 0;
|
|
|
|
$alert_email = read_config_option('alert_email');
|
|
|
|
if (api_plugin_is_enabled('maint') && plugin_maint_check_cacti_host($host['id'])) {
|
|
cacti_log('WARNING: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] is DOWN. Only logging, maint device', true, 'THOLD');
|
|
} else {
|
|
if (strtotime($host['status_fail_date']) > 192800 || strtotime($host['status_rec_date']) > 192800) {
|
|
$down_sec = db_fetch_cell_prepared('SELECT unix_timestamp(status_rec_date)-unix_timestamp(status_fail_date)
|
|
FROM host WHERE id = ?',
|
|
[$host['id']]);
|
|
|
|
$days = intval($down_sec / (60 * 60 * 24));
|
|
$remainder = $down_sec % (60 * 60 * 24);
|
|
$hours = intval($remainder / (60 * 60));
|
|
$remainder = $remainder % (60 * 60);
|
|
$minutes = intval($remainder / (60));
|
|
$last_state_duration = $days . 'd ' . $hours . 'h ' . $minutes . 'm';
|
|
} else {
|
|
$last_state_duration = __('N/A', 'thold');
|
|
}
|
|
|
|
$subject = read_config_option('thold_down_subject');
|
|
|
|
if ($subject == '') {
|
|
$subject = __('Devices Error: <DESCRIPTION> (<HOSTNAME>) is DOWN', 'thold');
|
|
}
|
|
|
|
$site = db_fetch_cell_prepared('SELECT name FROM sites WHERE id = ?', [$host['site_id']]);
|
|
|
|
if ($site == '') {
|
|
$site = 'Unspecified';
|
|
}
|
|
|
|
$subject = thold_str_replace('<HOSTNAME>', $host['hostname'], $subject);
|
|
$subject = thold_str_replace('<DESCRIPTION>', $host['description'], $subject);
|
|
$subject = thold_str_replace('<SITE>', $site, $subject);
|
|
$subject = thold_str_replace('<LOCATION>', $host['location'], $subject);
|
|
$subject = thold_str_replace('<DOWN/UP>', __('DOWN', 'thold'), $subject);
|
|
$subject = thold_str_replace('<DOWNTIME>', $last_state_duration, $subject);
|
|
$subject = thold_str_replace('<NOTES>', $host['notes'], $subject);
|
|
$subject = strip_tags($subject);
|
|
|
|
$msg = read_config_option('thold_down_text');
|
|
|
|
if ($msg == '') {
|
|
$msg = __('System Error : <DESCRIPTION> (<HOSTNAME>) is <DOWN/UP><br>Site: <SITE><br>Location: <LOCATION><br>Reason: <MESSAGE><br><br>Average system response : <AVG_TIME> ms<br>System availability: <AVAILABILITY><br>Total Checks Since Clear: <TOT_POLL><br>Total Failed Checks: <FAIL_POLL><br>Last Date Checked DOWN : <LAST_FAIL><br>Devices Previously UP for: <DOWNTIME><br>NOTE: <NOTES>', 'thold');
|
|
}
|
|
|
|
$msg = thold_str_replace('<SUBJECT>', $subject, $msg);
|
|
$msg = thold_str_replace('<HOSTNAME>', $host['hostname'], $msg);
|
|
$msg = thold_str_replace('<HOST_ID>', $host['id'], $msg);
|
|
$msg = thold_str_replace('<DESCRIPTION>', $host['description'], $msg);
|
|
$msg = thold_str_replace('<SITE>', $site, $msg);
|
|
$msg = thold_str_replace('<LOCATION>', $host['location'], $msg);
|
|
$msg = thold_str_replace('<UPTIME>', '', $msg);
|
|
$msg = thold_str_replace('<DOWNTIME>', $last_state_duration, $msg);
|
|
|
|
$msg = thold_str_replace('<TIME>', time(), $msg);
|
|
$msg = thold_str_replace('<DATE>', date(CACTI_DATE_TIME_FORMAT), $msg);
|
|
$msg = thold_str_replace('<DATE_RFC822>', date(DATE_RFC822), $msg);
|
|
|
|
$msg = thold_str_replace('<MESSAGE>', $host['status_last_error'], $msg);
|
|
$msg = thold_str_replace('<DOWN/UP>', __('DOWN', 'thold'), $msg);
|
|
$msg = thold_str_replace('<SNMP_HOSTNAME>', '', $msg);
|
|
$msg = thold_str_replace('<SNMP_LOCATION>', '', $msg);
|
|
$msg = thold_str_replace('<SNMP_CONTACT>', '', $msg);
|
|
$msg = thold_str_replace('<SNMP_SYSTEM>', '', $msg);
|
|
$msg = thold_str_replace('<LAST_FAIL>', $host['status_fail_date'], $msg);
|
|
$msg = thold_str_replace('<AVAILABILITY>', round(($host['availability']), 2) . ' %', $msg);
|
|
$msg = thold_str_replace('<CUR_TIME>', round(($host['cur_time']), 2), $msg);
|
|
$msg = thold_str_replace('<TOT_POLL>', $host['total_polls'], $msg);
|
|
$msg = thold_str_replace('<FAIL_POLL>', $host['failed_polls'], $msg);
|
|
$msg = thold_str_replace('<AVG_TIME>', round(($host['avg_time']), 2), $msg);
|
|
$msg = thold_str_replace('<NOTES>', $host['notes'], $msg);
|
|
$msg = thold_str_replace("\n", '<br>', $msg);
|
|
|
|
switch ($host['thold_send_email']) {
|
|
case '0': // Disabled
|
|
$alert_email = '';
|
|
|
|
break;
|
|
case '1': // Global List
|
|
break;
|
|
case '2': // Devices List Only
|
|
$alert_email = get_thold_notification_emails($host['thold_host_email']);
|
|
$notify_list_id = $host['thold_host_email'];
|
|
|
|
break;
|
|
case '3': // Global and Devices List
|
|
$alert_email = $alert_email . ',' . get_thold_notification_emails($host['thold_host_email']);
|
|
$notify_list_id = $host['thold_host_email'];
|
|
|
|
break;
|
|
}
|
|
|
|
api_plugin_hook_function(
|
|
'thold_device_down',
|
|
[
|
|
'device' => $host,
|
|
'subject' => $subject,
|
|
'message' => $msg,
|
|
'email' => $alert_email
|
|
]
|
|
);
|
|
|
|
cacti_log('WARNING: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] is down!', true, 'THOLD');
|
|
|
|
if ($alert_email == '' && $host['thold_send_email'] > 0) {
|
|
cacti_log('WARNING: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] can not send a Device down email for \'' . $host['description'] . '\' since the \'Alert Email\' setting is not set for Device!', true, 'THOLD');
|
|
} elseif ($host['thold_send_email'] == '0') {
|
|
cacti_log('NOTE: Device[' . $host['id'] . '] Hostname[' . $host['hostname'] . '] did not send a Device down email for \'' . $host['description'] . '\', disabled per Device setting!', true, 'THOLD');
|
|
} elseif ($alert_email != '') {
|
|
thold_mail($alert_email, '', '', $subject, $msg, '', '', $notify_list_id, $host, '', 7, 'thold_dhost_mail');
|
|
}
|
|
|
|
$command = read_config_option('thold_device_command');
|
|
|
|
if ($command != '') {
|
|
thold_putenv('THOLD_SUBJECT=' . $subject);
|
|
thold_putenv('THOLD_HOSTNAME=' . $host['hostname']);
|
|
thold_putenv('THOLD_HOST_ID=' . $host['id']);
|
|
thold_putenv('THOLD_DESCRIPTION=' . $host['description']);
|
|
thold_putenv('THOLD_SITE=' . $site);
|
|
thold_putenv('THOLD_LOCATION=' . $host['location']);
|
|
thold_putenv('THOLD_TIME=' . time());
|
|
thold_putenv('THOLD_DATE=' . date(CACTI_DATE_TIME_FORMAT));
|
|
thold_putenv('THOLD_DATE_RFC822=' . date(DATE_RFC822));
|
|
|
|
thold_putenv('THOLD_UPTIME=');
|
|
thold_putenv('THOLD_DOWNTIME=' . $last_time_duration);
|
|
thold_putenv('THOLD_MESSAGE=' . $host['status_last_error']);
|
|
thold_putenv('THOLD_DOWNUP=' . 'DOWN');
|
|
|
|
thold_putenv('THOLD_SNMP_HOSTNAME=' . $host['snmp_sysName']);
|
|
thold_putenv('THOLD_SNMP_LOCATION=' . $host['snmp_sysLocation']);
|
|
thold_putenv('THOLD_SNMP_CONTACT=' . $host['snmp_sysContact']);
|
|
thold_putenv('THOLD_SNMP_SYSTEM=');
|
|
thold_putenv('THOLD_LAST_FAIL=' . $host['status_fail_date']);
|
|
thold_putenv('THOLD_AVAILABILITY=' . $host['availability']);
|
|
thold_putenv('THOLD_TOT_POLL=' . $host['total_polls']);
|
|
thold_putenv('THOLD_FAIL_POLL=' . $host['failed_polls']);
|
|
thold_putenv('THOLD_CUR_TIME=' . $host['cur_time']);
|
|
thold_putenv('THOLD_AVG_TIME=' . $host['avg_time']);
|
|
$environment = thold_putenv('THOLD_NOTES=' . $host['notes']);
|
|
|
|
if (file_exists($command) && is_executable($command)) {
|
|
$output = [];
|
|
$return = 0;
|
|
|
|
if ($queue == '') {
|
|
exec($command, $output, $return);
|
|
|
|
cacti_log('Device Down Command for Device[' . $host['id'] . '] Command[' . $command . '] ExitStatus[' . $return . '] Output[' . implode(' ', $output) . ']', false, 'THOLD');
|
|
} else {
|
|
$data = [
|
|
'command' => $command,
|
|
'data' => $host,
|
|
'environment' => $environment
|
|
];
|
|
|
|
thold_notification_add('thold_dhost_cmd', $data, 'id', $notify_list_id, $host);
|
|
}
|
|
} else {
|
|
cacti_log('WARNING: Device Down Command for Device[' . $host['id'] . '] Command[' . $command . '] Is either Not found or Not executable!', false, 'THOLD');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Now lets record all failed hosts
|
|
if (read_config_option('remote_storage_method') == 1) {
|
|
db_execute_prepared('DELETE
|
|
FROM plugin_thold_host_failed
|
|
WHERE poller_id = ?',
|
|
[$config['poller_id']]);
|
|
|
|
$hosts = db_fetch_assoc_prepared('SELECT id, status, hostname
|
|
FROM host
|
|
WHERE disabled = ""
|
|
AND poller_id = ?
|
|
AND ((status != ? AND status != ?)
|
|
OR (status = ? AND status_event_count >= IF(thold_failure_count > 0, thold_failure_count, ?))) ',
|
|
[$config['poller_id'], HOST_UP, HOST_DOWN, HOST_DOWN, $ping_failure_count]);
|
|
|
|
set_config_option('time_last_change_thold_device', time());
|
|
} else {
|
|
db_execute('TRUNCATE plugin_thold_host_failed');
|
|
|
|
$hosts = db_fetch_assoc_prepared('SELECT id, status, hostname
|
|
FROM host
|
|
WHERE disabled = ""
|
|
AND ((status != ? AND status != ?)
|
|
OR (status = ? AND status_event_count >= IF(thold_failure_count > 0, thold_failure_count, ?))) ',
|
|
[HOST_UP, HOST_DOWN, HOST_DOWN, $ping_failure_count]);
|
|
|
|
set_config_option('time_last_change_thold_device', time());
|
|
}
|
|
|
|
if (cacti_sizeof($hosts)) {
|
|
$failed_ids = '';
|
|
|
|
foreach ($hosts as $host) {
|
|
// hosts in recovery status record only if they was in failed status
|
|
if (($host['status'] != HOST_RECOVERING) || ($host['status'] == HOST_RECOVERING && (is_array($failed) && array_search($host['id'], array_column($failed, 'host_id'), true) !== false))) {
|
|
$failed_ids .= ($failed_ids != '' ? '), (' : '(') . $host['id'];
|
|
}
|
|
}
|
|
|
|
$failed_ids .= $failed_ids != '' ? ')' : '';
|
|
|
|
if ($failed_ids != '') {
|
|
db_execute("INSERT INTO plugin_thold_host_failed
|
|
(host_id)
|
|
VALUES $failed_ids");
|
|
|
|
set_config_option('time_last_change_thold_device', time());
|
|
}
|
|
}
|
|
|
|
return $total_hosts;
|
|
}
|