$max_id) { $max_id = $device['device_id']; } } // Cleanup tables with links to devices that on longer exist foreach ($config['device_tables'] as $table) { $where = '`device_id` NOT IN (' . implode(',', $devices) . ') AND `device_id` < ?'; //$where = '`device_id` NOT IN (' . implode(',', $devices) . ') OR `device_id` > ?'; if ($table === 'observium_processes') { $where .= ' AND `device_id` != 0'; } elseif ($table === 'eventlog') { // Global events with device_id = 0 $where .= " AND `entity_type` NOT IN ('global', 'info')"; } $rows = dbFetchRows("SELECT 1 FROM `$table` WHERE $where", [ $max_id ], $test); $count = safe_count($rows); if ($count) { if ($prompt) { $answer = print_prompt("$count rows in table '$table' for non-existing devices will be deleted"); } if ($answer) { // IP addresses need additionally check if associated network is empty if ($table === 'ipv4_addresses') { $network_table = 'ipv4_networks'; $network_where = '`ipv4_network_id` = ?'; $network_ids = dbFetchColumn("SELECT DISTINCT `ipv4_network_id` FROM `$table` WHERE $where", array($max_id)); print_debug_vars($network_ids); } elseif ($table === 'ipv6_addresses') { $network_table = 'ipv6_networks'; $network_where = '`ipv6_network_id` = ?'; $network_ids = dbFetchColumn("SELECT DISTINCT `ipv6_network_id` FROM `$table` WHERE $where", array($max_id)); print_debug_vars($network_ids); } // Remove stale entries print_debug("Database cleanup for table '$table': deleted $count entries"); if (!$test) { $table_status = dbDelete($table, $where, [ $max_id ]); logfile("housekeeping.log", "Database cleanup for table '$table': deleted $count entries"); } // Clean network ids after delete ip addresses if network unused if ($table_status && ($table === 'ipv4_addresses' || $table === 'ipv6_addresses')) { foreach ($network_ids as $network_id) { if (!dbExist($table, $network_where, [ $network_id ], $test) && !$test) { $network_status = dbDelete($network_table, $network_where, array($network_id)); } } } } } elseif ($prompt) { print_message("No orphaned rows found in table '$table'."); } } // Cleanup autodiscovery entries if (dbExist('autodiscovery', '`remote_device_id` IS NOT NULL AND `remote_device_id` NOT IN (SELECT `device_id` FROM `devices`)', NULL, $test)) { if (!$test) { $table_status = dbDelete('autodiscovery', '`remote_device_id` IS NOT NULL AND `remote_device_id` NOT IN (SELECT `device_id` FROM `devices`)'); logfile("housekeeping.log", "Deleted stale autodiscovery entries."); } print_debug("Deleted stale autodiscovery entries."); } // Cleanup common entity tables with links to devices that no longer exist // Loop for found stale entity entries /* * Probably not the best idea to remove user-generated configuration like this, this very occasionally seems to delete billing ports * $where = " WHERE " . generate_query_values([ 'bill', 'group' ], 'entity_type', '!=', FALSE); // Exclude pseudo-entities from permissions checks foreach ($config['entity_tables'] as $table) { $query = "SELECT DISTINCT `entity_type` FROM `$table` $where"; foreach (dbFetchColumn($query, NULL, $test) as $entity_type) { $translate = entity_type_translate_array($entity_type); if (safe_empty($translate['device_id_field'])) { continue; } $id_field = $translate['id_field']; $query = 'SELECT `entity_id` FROM `'.$table.'` WHERE `entity_type` = ? AND `entity_id` NOT IN (SELECT `' . $id_field . '` FROM `' . $translate['table'] . '`)'; $ids = dbFetchColumn($query, [ $entity_type ], $test); $count = safe_count($ids); if ($count) { if ($prompt) { $answer = print_prompt("$count rows in table '$table' for non-existing '$entity_type' entities will be deleted"); } // Remove stale entries print_debug("Database cleanup for table '$table': deleted $count '$entity_type' entities"); if (!$test) { $table_status = dbDelete($table, "`entity_type` = ? ".generate_query_values($ids, 'entity_id'), [ $entity_type ]); logfile("housekeeping.log", "Database cleanup for table '$table': deleted $count '$entity_type' entities"); } } elseif ($prompt) { print_message("No orphaned rows found in table '$table' for '$entity_type' entities."); } } } */ // Cleanup duplicate entries in the device_graphs table $graphs = []; foreach (dbFetchRows("SELECT * FROM `device_graphs`", NULL, $test) as $entry) { $graphs[$entry['device_id']][$entry['graph']][] = $entry['device_graph_id']; } print_debug_vars($graphs); foreach ($graphs as $device_id => $device_graph) { foreach ($device_graph as $graph => $data) { if (safe_count($data) > 1) { // More than one entry for a single graph type for this device, let's clean up. // Leave the first entry intact, chop it off the array $device_graph_ids = array_slice($data, 1); $device_graph_count = safe_count($device_graph_ids); if ($prompt) { $answer = print_prompt($device_graph_count . " duplicate graph rows of type $graph for device $device_id will be deleted"); } if ($answer) { if (!$test) { $table_status = dbDelete('device_graphs', "`device_graph_id` IN (?)", [ $device_graph_ids ]); logfile("housekeeping.log", "Deleted " . $device_graph_count . " duplicate graph rows of type $graph for device $device_id"); } print_debug("Deleted " . $device_graph_count . " duplicate graph rows of type $graph for device $device_id"); } } } } // EOF