Observium_CE/discovery.php

331 lines
12 KiB
PHP
Executable File

#!/usr/bin/env php
<?php
/**
* Observium
*
* This file is part of Observium.
*
* @package observium
* @subpackage discovery
* @copyright (C) Adam Armstrong
*
*/
chdir(dirname($argv[0]));
// Get options before definitions!
$options = getopt("h:i:m:n:p:U:dfquaMV");
include("includes/observium.inc.php");
include("includes/discovery/functions.inc.php");
$cli = TRUE;
//if (is_cron()) { $options['q'] = TRUE; } // Set quiet for cron
$start = utime();
$runtime_stats = [];
if (isset($options['V'])) {
if (is_array($options['V'])) {
// Show more detailed Observium version and installed software versions
print_versions();
} else {
print_message(OBSERVIUM_PRODUCT . " " . OBSERVIUM_VERSION_LONG);
}
exit;
}
if (isset($options['M'])) {
print_message(OBSERVIUM_PRODUCT . " " . OBSERVIUM_VERSION);
print_message('Enabled discovery modules:');
$m_disabled = [];
foreach ($config['discovery_modules'] as $module => $ok) {
if ($ok) {
print_message(' ' . $module);
} else {
$m_disabled[] = $module;
}
}
if (count($m_disabled)) {
print_message('Disabled discovery modules:');
print_message(' ' . implode("\n ", $m_disabled));
}
exit;
}
if (!isset($options['q'])) {
print_cli_banner();
if (OBS_DEBUG) {
print_versions();
}
// Warning about obsolete configs.
if (print_obsolete_config()) {
echo PHP_EOL;
}
}
if (isset($options['u']) || isset($options['U']) ||
(isset($options['h']) && in_array($options['h'], [ 'all', 'odd', 'even', 'none' ]))) {
$options['u'] = TRUE;
if (isset($options['f'])) {
//$options['U'] = TRUE;
}
include($config['install_dir'] . '/includes/update/update.php');
if ($updating) {
// DB schema updated. force alert/groups update
$options['a'] = TRUE;
}
// check remote poller params
if (OBS_DISTRIBUTED) {
check_local_poller();
}
} elseif (!isset($options['q'])) {
// Warn about need DB schema update
$db_version = get_db_version();
$db_version = sprintf("%03d", $db_version + 1);
if (is_file($config['install_dir'] . "/update/$db_version.sql") || is_file($config['install_dir'] . "/update/$db_version.php")) {
print_warning("Your database schema is old and needs updating. Run from console:\n " . $config['install_dir'] . "/discovery.php -u");
}
unset($db_version);
}
$where = '';
if (isset($options['h'])) {
$params = [];
switch ($options['h']) {
case 'odd':
$options['n'] = 1;
$options['i'] = 2;
break;
case 'even':
$options['n'] = 0;
$options['i'] = 2;
break;
case 'all':
$where = ' ';
$doing = 'all';
break;
case 'new':
$where = ' AND (`last_discovered` IS NULL OR `last_discovered` = ? OR `force_discovery` = ?)';
$params[] = '0000-00-00 00:00:00';
$params[] = 1;
$doing = 'new';
// add new devices on remote poller from actions queue
if (OBS_DISTRIBUTED && function_exists('run_action_queue')) {
run_action_queue('device_add');
//run_action_queue('device_rename');
//run_action_queue('device_delete');
// Update alert and group tables
run_action_queue('tables_update');
}
break;
case 'none':
//$options['u'] = TRUE;
break;
default:
$doing = $options['h'];
if (is_numeric($options['h'])) {
$where = ' AND `device_id` = ?';
$params[] = $options['h'];
} else {
$where = ' AND `hostname` LIKE ?';
$params[] = str_replace('*', '%', $options['h']);
}
}
}
if (isset($options['i'], $options['n']) && $options['i']) {
$where .= ' AND MOD(device_id,' . $options['i'] . ') = ?';
$params[] = $options['n'];
$doing = $options['n'] . '/' . $options['i'];
}
if (!$where && !$options['u'] && !isset($options['a'])) {
print_message("%n
USAGE:
$scriptname [-dquV] [-i instances] [-n number] [-m module] [-h device]
EXAMPLE:
-h <device id> | <device hostname wildcard> Discover single device
-h odd Discover odd numbered devices (same as -i 2 -n 0)
-h even Discover even numbered devices (same as -i 2 -n 1)
-h all Discover all devices
-h new Discover all devices that have not had a discovery run before
-i <instances> -n <number> Discover as instance <number> of <instances>
Instances start at 0. 0-3 for -n 4
OPTIONS:
-h Device hostname, id or key odd/even/all/new.
-i Discovery instance.
-n Discovery number.
-q Quiet output.
-a Update Groups/Alerts table
-u Upgrade DB schema
-M Show globally enabled/disabled modules and exit.
-V Show version and exit.
DEBUGGING OPTIONS:
-f Force requested option
-d Enable debugging output.
-dd More verbose debugging output.
-m Specify modules (separated by commas) to be run.
%rInvalid arguments!%n", 'color', FALSE);
}
if ($config['version_check'] && ($options['h'] !== 'new' || $options['u'])) {
include($config['install_dir'] . '/includes/versioncheck.inc.php');
}
if (!$where) {
// Only update Group/Alert tables
if (isset($options['a'])) {
// Distributed handling doesn't make sense here. It's just database action.
// if (OBS_DISTRIBUTED && function_exists('run_action_queue')) {
//run_action_queue('device_add');
//run_action_queue('device_rename');
//run_action_queue('device_delete');
// Update alert and group tables
// run_action_queue('tables_update', $options);
// } else {
$silent = isset($options['q']);
if (function_exists('update_group_tables')) {
update_group_tables($silent);
} // Not exist in CE
if (function_exists('update_alert_tables')) {
update_alert_tables($silent);
}
// }
}
exit;
}
// For not new devices discovery, skip down devices
if ($options['h'] !== 'new' && !isset($options['f'])) {
$where .= ' AND `status` = ?';
$params[] = 1;
}
// Discovered device counter
$discovered_devices = 0;
print_cli_heading("%WStarting discovery run at " . date("Y-m-d H:i:s"), 0);
$where .= ' AND `poller_id` = ?';
$params[] = $config['poller_id'];
foreach (dbFetchRows("SELECT * FROM `devices` WHERE `disabled` = 0 $where ORDER BY `last_discovered_timetaken` ASC", $params) as $device) {
// Additional check if device SNMPable, because during
// discovery many devices (long time), some device can be switched off
if ($options['h'] === 'new' || is_snmpable($device)) {
$discover_status = discover_device($device, $options);
} else {
$string = "Device '" . $device['hostname'] . "' skipped, because switched off during runtime discovery process.";
print_debug($string);
logfile($argv[0] . ": $string");
$discover_status = FALSE;
}
if ($discover_status !== FALSE) {
$discovered_devices++;
}
}
print_cli_heading("%WFinished discovery run at " . date("Y-m-d H:i:s"), 0);
$discovery_time = elapsed_time($start, 4);
// Update Group/Alert tables
if (($discovered_devices && !isset($options['m'])) || isset($options['a'])) {
$silent = isset($options['q']);
if (OBS_DISTRIBUTED && !isset($options['a']) && function_exists('add_action_queue') &&
$action_id = add_action_queue('tables_update', 'discovery', ['silent' => $silent])) {
print_message("Update alert and group tables added to queue [$action_id].");
//log_event("Device with hostname '$hostname' added to queue [$action_id] for addition on remote Poller [{$vars['poller_id']}].", NULL, 'info', NULL, 7);
} else {
// Not exist in CE
if (function_exists('update_group_tables')) {
// update_group_tables($silent);
update_group_tables();
}
if (function_exists('update_alert_tables')) {
update_alert_tables($silent);
}
}
}
if ($discovered_devices) {
// Single device ID convert to hostname for log
if (is_numeric($doing)) {
$doing = $device['hostname'];
// This discovery passed from wrapper and with process id
if (OBS_DISTRIBUTED && !$options['u']) {
check_local_poller();
}
}
} elseif (!isset($options['q']) && !$options['u']) {
print_warning("WARNING: 0 devices discovered." . ($options['h'] !== 'new' ? " Did you specify a device that does not exist?" : ''));
}
$string = $argv[0] . ": $doing - $discovered_devices devices discovered in $discovery_time secs";
print_debug($string);
logfile($string);
// Clean stale observium processes
$process_sql = "SELECT * FROM `observium_processes` WHERE `poller_id` = ? AND `process_start` < ?";
foreach (dbFetchRows($process_sql, [ $config['poller_id'], get_time('fourhour') ]) as $process) {
// We found processes in DB, check if it exists on a system
print_debug_vars($process);
$pid_info = get_pid_info($process['process_pid']);
if (is_array($pid_info) && str_contains($pid_info['COMMAND'], $process['process_name'])) {
// Process still running
} else {
// Remove stalled DB entries
dbDelete('observium_processes', '`process_id` = ?', [$process['process_id']]);
print_debug("Removed stale process entry from DB (cmd: '" . $process['process_command'] . "', PID: '" . $process['process_pid'] . "')");
}
}
if (!isset($options['q'])) {
if ($config['snmp']['hide_auth']) {
print_debug("NOTE, \$config['snmp']['hide_auth'] is set to TRUE, snmp community and snmp v3 auth hidden from debug output.");
}
print_cli_data('Devices Discovered', $discovered_devices, 0);
print_cli_data('Discovery Time', $discovery_time . " secs", 0);
print_cli_data('Definitions', $defs_time . " secs", 0);
print_cli_data('Memory usage', format_bytes(memory_get_usage(TRUE), 2, 4) .
' (peak: ' . format_bytes(memory_get_peak_usage(TRUE), 2, 4) . ')', 0);
print_cli_data('MySQL Usage', 'Cell[' . ($db_stats['fetchcell'] + 0) . '/' . round($db_stats['fetchcell_sec'] + 0, 3) . 's]' .
' Row[' . ($db_stats['fetchrow'] + 0) . '/' . round($db_stats['fetchrow_sec'] + 0, 3) . 's]' .
' Rows[' . ($db_stats['fetchrows'] + 0) . '/' . round($db_stats['fetchrows_sec'] + 0, 3) . 's]' .
' Column[' . ($db_stats['fetchcol'] + 0) . '/' . round($db_stats['fetchcol_sec'] + 0, 3) . 's]' .
' Update[' . ($db_stats['update'] + 0) . '/' . round($db_stats['update_sec'] + 0, 3) . 's]' .
' Insert[' . ($db_stats['insert'] + 0) . '/' . round($db_stats['insert_sec'] + 0, 3) . 's]' .
' Delete[' . ($db_stats['delete'] + 0) . '/' . round($db_stats['delete_sec'] + 0, 3) . 's]', 0);
$rrd_times = [];
foreach ($GLOBALS['rrdtool'] as $cmd => $data) {
$rrd_times[] = $cmd . "[" . $data['count'] . "/" . round($data['time'], 3) . "s]";
}
print_cli_data('RRDTool Usage', implode(" ", $rrd_times), 0);
}
// EOF