Skip to content

Commit

Permalink
Fixing Iseue #4616 - Plugin Replication Issues
Browse files Browse the repository at this point in the history
- When performing plugin actions from the Cacti UI, replication should be forced to Remote Collectors
- max_packet was not being calculated correctly.
- Cacti log function logging on verbosity NONE
  • Loading branch information
TheWitness committed Mar 13, 2022
1 parent 107227a commit 5b49db4
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Expand Up @@ -83,6 +83,7 @@ Cacti CHANGELOG
-issue#4612: Cacti's cacti_remembers Cookie does not include the secure attribute required for SameSite support
-issue#4613: Cacti replication can not correct table structure changes in newer versions of MySQL/MariaDB
-issue#4614: Cacti can not differentiate between execution remotely between the main poller loop vs. poller bottom
-issue#4616: When performing plugin actions from the Cacti UI, replication should be forced to Remote Collectors
-feature: Expose hidden Language Translation setting l10n_language_handler
-feature: Allow a Device to be a part of a Report outside of a Tree
-feature: Allow Basic Authentication to display customer login failed message
Expand Down
54 changes: 53 additions & 1 deletion lib/plugins.php
Expand Up @@ -570,7 +570,7 @@ function api_plugin_db_changes_remove($plugin) {
}
}

function api_plugin_db_add_column ($plugin, $table, $column) {
function api_plugin_db_add_column($plugin, $table, $column) {
global $config, $database_default;

// Example: api_plugin_db_add_column ('thold', 'plugin_config',
Expand Down Expand Up @@ -728,6 +728,8 @@ function api_plugin_install($plugin) {
array($plugin));
}
}

api_plugin_replicate_config();
}

function api_plugin_uninstall_integrated() {
Expand Down Expand Up @@ -766,6 +768,8 @@ function api_plugin_uninstall($plugin, $tables = true) {
WHERE plugin = ?',
array($plugin));
}

api_plugin_replicate_config();
}

function api_plugin_check_config($plugin) {
Expand Down Expand Up @@ -821,6 +825,34 @@ function api_plugin_disable($plugin) {
SET status = 4
WHERE directory = ?',
array($plugin));

api_plugin_replicate_config();
}

function api_plugin_replicate_config() {
global $config;

include_once($config['base_path'] . '/lib/poller.php');

$gone_time = read_config_option('poller_interval') * 2;

$pollers = array_rekey(
db_fetch_assoc('SELECT
id,
UNIX_TIMESTAMP() - UNIX_TIMESTAMP(last_status) AS last_polled
FROM poller
WHERE id > 1
AND disabled=""'),
'id', 'last_polled'
);

if (cacti_sizeof($pollers)) {
foreach($pollers as $poller_id => $last_polled) {
if ($last_polled < $gone_time) {
replicate_out($poller_id, 'plugins');
}
}
}
}

function api_plugin_disable_all($plugin) {
Expand All @@ -830,6 +862,8 @@ function api_plugin_disable_all($plugin) {
SET status = 4
WHERE directory = ?',
array($plugin));

api_plugin_replicate_config();
}

function api_plugin_moveup($plugin) {
Expand All @@ -851,6 +885,8 @@ function api_plugin_moveup($plugin) {
db_execute_prepared('UPDATE plugin_config SET id = ? WHERE id = ?', array($prior_id, $id));
db_execute_prepared('UPDATE plugin_config SET id = ? WHERE id = ?', array($id, $temp_id));
}

api_plugin_replicate_config();
}

function api_plugin_movedown($plugin) {
Expand All @@ -862,6 +898,8 @@ function api_plugin_movedown($plugin) {
db_execute_prepared('UPDATE plugin_config SET id = ? WHERE id = ?', array($temp_id, $next_id));
db_execute_prepared('UPDATE plugin_config SET id = ? WHERE id = ?', array($next_id, $id));
db_execute_prepared('UPDATE plugin_config SET id = ? WHERE id = ?', array($id, $temp_id));

api_plugin_replicate_config();
}

function api_plugin_register_hook($plugin, $hook, $function, $file, $enable = false) {
Expand Down Expand Up @@ -912,19 +950,25 @@ function api_plugin_register_hook($plugin, $hook, $function, $file, $enable = fa
AND `hook` = ?",
array($function, $status, $file, $plugin, $hook));
}

api_plugin_replicate_config();
}

function api_plugin_remove_hooks($plugin) {
db_execute_prepared('DELETE FROM plugin_hooks
WHERE name = ?',
array($plugin));

api_plugin_replicate_config();
}

function api_plugin_enable_hooks($plugin) {
db_execute_prepared('UPDATE plugin_hooks
SET status = 1
WHERE name = ?',
array($plugin));

api_plugin_replicate_config();
}

function api_plugin_disable_hooks($plugin) {
Expand All @@ -935,13 +979,17 @@ function api_plugin_disable_hooks($plugin) {
AND hook != 'config_arrays'
AND hook != 'config_form'",
array($plugin));

api_plugin_replicate_config();
}

function api_plugin_disable_hooks_all($plugin) {
db_execute_prepared("UPDATE plugin_hooks
SET status = 0
WHERE name = ?",
array($plugin));

api_plugin_replicate_config();
}

function api_plugin_register_realm($plugin, $file, $display, $admin = true) {
Expand Down Expand Up @@ -1043,6 +1091,8 @@ function api_plugin_register_realm($plugin, $file, $display, $admin = true) {
WHERE id = ?',
array($display, $file, $realm_id));
}

api_plugin_replicate_config();
}

function api_plugin_remove_realms($plugin) {
Expand All @@ -1065,6 +1115,8 @@ function api_plugin_remove_realms($plugin) {
db_execute_prepared('DELETE FROM plugin_realms
WHERE plugin = ?',
array($plugin));

api_plugin_replicate_config();
}

function api_plugin_load_realms() {
Expand Down
39 changes: 26 additions & 13 deletions lib/poller.php
Expand Up @@ -1323,6 +1323,12 @@ function replicate_out($remote_poller_id = 1, $class = 'all') {
$data = db_fetch_assoc('SELECT * FROM poller');
replicate_out_table($rcnn_id, $data, 'poller', $remote_poller_id);

$data = db_fetch_assoc('SELECT * FROM version');
replicate_out_table($rcnn_id, $data, 'version', $remote_poller_id);
}

// Plugin tables
if ($class == 'all' || $class == 'plugins') {
$data = db_fetch_assoc('SELECT * FROM plugin_config');
replicate_out_table($rcnn_id, $data, 'plugin_config', $remote_poller_id);

Expand All @@ -1331,9 +1337,6 @@ function replicate_out($remote_poller_id = 1, $class = 'all') {

$data = db_fetch_assoc('SELECT * FROM plugin_realms');
replicate_out_table($rcnn_id, $data, 'plugin_realms', $remote_poller_id);

$data = db_fetch_assoc('SELECT * FROM version');
replicate_out_table($rcnn_id, $data, 'version', $remote_poller_id);
}

// Auth tables
Expand Down Expand Up @@ -1501,7 +1504,9 @@ function replicate_out($remote_poller_id = 1, $class = 'all') {
replicate_out_table($rcnn_id, $data, 'data_input_data', $remote_poller_id);
}

api_plugin_hook_function('replicate_out', array('remote_poller_id' => $remote_poller_id, 'rcnn_id' => $rcnn_id, 'class' => $class));
if ($class == 'all') {
api_plugin_hook_function('replicate_out', array('remote_poller_id' => $remote_poller_id, 'rcnn_id' => $rcnn_id, 'class' => $class));
}

$stats = db_fetch_row_prepared('SELECT
SUM(CASE WHEN action=0 THEN 1 ELSE 0 END) AS snmp,
Expand All @@ -1518,8 +1523,10 @@ function replicate_out($remote_poller_id = 1, $class = 'all') {
array($stats['snmp'], $stats['script'], $stats['server'], $remote_poller_id));
}

replicate_log('Synchronization of Poller ' . $remote_poller_id . ' completed');
raise_message('poller_sync');
if ($class != 'plugins' && $config['is_web']) {
replicate_log('Synchronization of Poller ' . $remote_poller_id . ' completed', POLLER_VERBOSITY_LOW);
raise_message('poller_sync');
}

return true;
}
Expand All @@ -1540,7 +1547,7 @@ function replicate_out($remote_poller_id = 1, $class = 'all') {
*
* @return (void)
*/
function replicate_out_table($conn, &$data, $table, $remote_poller_id, $truncate = true, $exclude = false) {
function replicate_out_table($conn, &$data, $table, $remote_poller_id, $truncate = true, $exclude = false, $level = POLLER_VERBOSITY_NONE) {
if (cacti_sizeof($data)) {
/* check if the table structure changed, and if so, recreate */
$local_columns = db_fetch_assoc('SHOW COLUMNS FROM ' . $table);
Expand All @@ -1556,10 +1563,10 @@ function replicate_out_table($conn, &$data, $table, $remote_poller_id, $truncate
}

if (cacti_sizeof($local_columns) != cacti_sizeof($remote_columns)) {
replicate_log('NOTE: Replicate Out Detected a Table Structure Change for ' . $table);
replicate_log('NOTE: Replicate Out Detected a Table Structure Change for ' . $table, $level);
$create = db_fetch_row('SHOW CREATE TABLE ' . $table);
if (isset($create["CREATE TABLE `$table`"]) || isset($create['Create Table'])) {
replicate_log('NOTE: Replication Recreating Remote Table Structure for ' . $table);
replicate_log('NOTE: Replication Recreating Remote Table Structure for ' . $table, $level);
db_execute('DROP TABLE IF EXISTS ' . $table, true, $conn);

if (isset($create["CREATE TABLE `$table`"])) {
Expand Down Expand Up @@ -1634,7 +1641,7 @@ function replicate_out_table($conn, &$data, $table, $remote_poller_id, $truncate
$rows_done += $rows_affected;

if ($rows_log) {
replicate_log('NOTE: Table ' . $table . ' Replicated to Remote Poller ' . $remote_poller_id . ' With ' . $rows_done . ' Rows Updated');
replicate_log('NOTE: Table ' . $table . ' Replicated to Remote Poller ' . $remote_poller_id . ' With ' . $rows_done . ' Rows Updated', $level);
}
$sql = '';
$rowcnt = 0;
Expand All @@ -1646,20 +1653,20 @@ function replicate_out_table($conn, &$data, $table, $remote_poller_id, $truncate
$rows_done += db_affected_rows($conn);
}

replicate_log('INFO: Table ' . $table . ' Replicated to Remote Poller ' . $remote_poller_id . ' With ' . $rows_done . ' Rows Updated');
replicate_log('INFO: Table ' . $table . ' Replicated to Remote Poller ' . $remote_poller_id . ' With ' . $rows_done . ' Rows Updated', $level);
} else {
if (db_table_exists($table, true, $conn)) {
db_execute("TRUNCATE TABLE $table", true, $conn);
}

replicate_log('INFO: Table ' . $table . ' Not Replicated to Remote Poller ' . $remote_poller_id . ' Due to No Rows Found');
replicate_log('INFO: Table ' . $table . ' Not Replicated to Remote Poller ' . $remote_poller_id . ' Due to No Rows Found', $level);
}
}

function replicate_log($text, $level = POLLER_VERBOSITY_NONE) {
if (defined('IN_CACTI_INSTALL')) {
log_install_and_file($level, $text, 'REPLICATE', true);
} else {
} elseif ($level != POLLER_VERBOSITY_NONE) {
cacti_log($text, false, 'REPLICATE', $level);
}
}
Expand Down Expand Up @@ -1767,6 +1774,12 @@ function poller_push_reindex_data_to_poller($device_id = 0, $data_query_id = 0,
function replicate_table_to_poller($conn, &$data, $table, $exclude = false) {
$max_packet = db_fetch_row("SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'", true, $conn);

if (cacti_sizeof($max_packet)) {
$max_packet = $max_packet['Value'];
} else {
$max_packet = 2500000;
}

if (cacti_sizeof($data)) {
$prefix = "INSERT INTO $table (";
$suffix = ' ON DUPLICATE KEY UPDATE ';
Expand Down

0 comments on commit 5b49db4

Please sign in to comment.