function discover_new_device_ip($host) { global $config; if (match_network($config['autodiscovery']['ip_nets'], $host)) { if (isPingable($host)) { echo "Pingable "; foreach ($config['snmp']['community'] as $community) { $device = deviceArray($host, $community, "v2c", "161", "udp", NULL); print_message("Trying community {$community} ..."); if (isSNMPable($device)) { echo "SNMPable "; $snmphost = snmp_get($device, "sysName.0", "-Oqv", "SNMPv2-MIB"); if (dbFetchCell("SELECT COUNT(device_id) FROM devices WHERE sysName = ?", array($snmphost)) == '0') { $device_id = createHost($snmphost, $community, "v2c", "161", "udp"); $device = device_by_id_cache($device_id, 1); array_push($GLOBALS['devices'], $device); return $device_id; } else { echo "Already have host with sysName {$snmphost}\n"; } } } } } }
function perform_snmp_scan($net) { global $stats, $config, $debug, $vdebug; echo 'Range: ' . $net->network . '/' . $net->bitmask . PHP_EOL; $config['snmp']['timeout'] = 1; $config['snmp']['retries'] = 0; $config['fping_options']['retries'] = 0; $start = ip2long($net->network); $end = ip2long($net->broadcast) - 1; while ($start++ < $end) { $stats['count']++; $host = long2ip($start); if (match_network($config['autodiscovery']['nets-exclude'], $host)) { echo '|'; continue; } $test = isPingable($host); if ($test['result'] === false) { echo '.'; continue; } if (ip_exists($host)) { $stats['known']++; echo '*'; continue; } foreach (array('udp', 'tcp') as $transport) { try { addHost(gethostbyaddr($host), '', $config['snmp']['port'], $transport, $config['distributed_poller_group']); $stats['added']++; echo '+'; break; } catch (HostExistsException $e) { $stats['known']++; echo '*'; break; } catch (HostUnreachablePingException $e) { echo '.'; break; } catch (HostUnreachableException $e) { if ($debug) { print_error($e->getMessage() . " over {$transport}"); foreach ($e->getReasons() as $reason) { echo " {$reason}\n"; } } if ($transport == 'tcp') { // tried both udp and tcp without success $stats['failed']++; echo '-'; } } } } echo PHP_EOL; }
/** * Observium * * This file is part of Observium. * * @package observium * @subpackage discovery * @subpackage functions * @author Adam Armstrong <*****@*****.**> * @copyright (C) 2006-2014 Adam Armstrong * */ function discover_new_device_ip($host, $source = 'xdp', $protocol = NULL, $device = NULL, $port = NULL) { global $config; print_debug("Discovering possible new device on {$host}"); if ($config['autodiscovery'][$source]) { if (match_network($config['autodiscovery']['ip_nets'], $host)) { $db = dbFetchRow("SELECT * FROM ipv4_addresses AS A, ports AS P, devices AS D WHERE A.ipv4_address = ? AND P.port_id = A.port_id AND D.device_id = P.device_id", array($host)); if (is_array($db)) { print_debug("Already have {$host} on " . $db['hostname']); } else { if (isPingable($host)) { echo "Pingable "; foreach ($config['snmp']['community'] as $community) { $newdevice = deviceArray($host, $community, "v2c", "161", "udp", NULL); print_message("Trying community {$community} ..."); if (isSNMPable($newdevice)) { echo "SNMPable "; $snmphost = snmp_get($newdevice, "sysName.0", "-Oqv", "SNMPv2-MIB"); if (dbFetchCell("SELECT COUNT(device_id) FROM devices WHERE sysName = ?", array($snmphost)) == '0') { $device_id = createHost($snmphost, $community, "v2c", "161", "udp"); $newdevice = device_by_id_cache($device_id, 1); array_push($GLOBALS['devices'], $newdevice); if (!$protocol) { $protocol = strtoupper($source); } if ($port) { humanize_port($port); log_event("Device autodiscovered through {$protocol} on " . $device['hostname'] . " (port " . $port['label'] . ")", $remote_device_id, 'interface', $port['port_id']); } else { log_event("Device autodiscovered through {$protocol} on " . $device['hostname'], $remote_device_id); } return $device_id; } else { echo "Already have host with sysName {$snmphost}\n"; } } } } else { print_debug("IP not pingable."); } } } else { print_debug("Host does not match configured nets"); } } else { print_debug("Source {$source} disabled for autodiscovery!"); } }
function perform_snmp_scan($net) { global $stats, $config, $quiet; echo 'Range: ' . $net->network . '/' . $net->bitmask . PHP_EOL; $config['snmp']['timeout'] = 1; $config['snmp']['retries'] = 0; $config['fping_options']['retries'] = 0; $start = ip2long($net->network); $end = ip2long($net->broadcast) - 1; while ($start++ < $end) { $stats['count']++; $device_id = false; $host = long2ip($start); $test = isPingable($host); if ($test['result'] === false) { echo '.'; continue; } if (ip_exists($host)) { $stats['known']++; echo '*'; continue; } foreach (array('udp', 'tcp') as $transport) { if ($device_id !== false && $device_id > 0) { $stats['added']++; echo '+'; } else { if ($device_id === 0) { $stats['failed']++; echo '-'; break; } } $device_id = addHost(gethostbyaddr($host), '', $config['snmp']['port'], $transport, $quiet, $config['distributed_poller_group'], 0); } } echo PHP_EOL; }
function add_device($host, $snmpver = array(), $port = '161', $transport = 'udp', $error = FALSE) { global $config; // If $error set as TRUE break recursive function execute if ($error) { return FALSE; } // Reset snmp timeout and retries options for speedup device adding unset($config['snmp']['timeout'], $config['snmp']['retries']); list($hostshort) = explode(".", $host); // Test if host exists in database if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `hostname` = ?", array($host)) == '0') { // Test DNS lookup. if (gethostbyname6($host, TRUE)) { // Test reachability if (isPingable($host)) { // Test directory exists in /rrd/ if (!$config['rrd_override'] && file_exists($config['rrd_dir'] . '/' . $host)) { print_error("目录 rrd/{$host} 已经存在."); return FALSE; } if (empty($snmpver)) { foreach (array('v2c', 'v3', 'v1') as $snmpver) { // Try SNMP v2c, v3 and v1 $ret = add_device($host, $snmpver, $port, $transport, $error); if ($ret === FALSE) { $error = TRUE; } elseif (is_numeric($ret) && $ret > 0) { return $ret; } } } if ($snmpver === "v3") { // Try each set of parameters from config foreach ($config['snmp']['v3'] as $v3) { $device = deviceArray($host, NULL, $snmpver, $port, $transport, $v3); print_message("Trying v3 parameters " . $v3['authname'] . "/" . $v3['authlevel'] . " ... "); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { $device_id = createHost($host, NULL, $snmpver, $port, $transport, $v3); return $device_id; } } else { print_warning("证书没有回应 " . $v3['authname'] . "/" . $v3['authlevel'] . " using {$snmpver}."); } } } elseif ($snmpver === "v2c" || $snmpver === "v1") { // Try each community from config foreach ($config['snmp']['community'] as $community) { $device = deviceArray($host, $community, $snmpver, $port, $transport, NULL); print_message("尝试 {$snmpver} community {$community} ..."); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { $device_id = createHost($host, $community, $snmpver, $port, $transport); return $device_id; } } else { print_warning("Community 没有应答 {$community} 使用 {$snmpver}."); } } } else { print_error("不支持的协议版本 \"{$snmpver}\"."); } if (!$device_id) { // Failed SNMP print_error("不可到达的 {$host} 与给定 SNMP community 使用 {$snmpver}."); } } else { // failed Reachability print_error("无法 ping {$host}."); } } else { // Failed DNS lookup print_error("无法解析 {$host}."); } } else { // found in database print_error("已有设备 {$host}."); } return FALSE; }
function poll_device($device, $options) { global $config, $device, $polled_devices, $db_stats, $memcache; $attribs = get_dev_attribs($device['device_id']); $status = 0; unset($array); $device_start = utime(); // Start counting device poll time echo $device['hostname'] . ' ' . $device['device_id'] . ' ' . $device['os'] . ' '; if ($config['os'][$device['os']]['group']) { $device['os_group'] = $config['os'][$device['os']]['group']; echo '(' . $device['os_group'] . ')'; } echo "\n"; unset($poll_update); unset($poll_update_query); unset($poll_separator); $poll_update_array = array(); $update_array = array(); $host_rrd = $config['rrd_dir'] . '/' . $device['hostname']; if (!is_dir($host_rrd)) { mkdir($host_rrd); echo "Created directory : {$host_rrd}\n"; } $address_family = snmpTransportToAddressFamily($device['transport']); $ping_response = isPingable($device['hostname'], $address_family, $attribs); $device_perf = $ping_response['db']; $device_perf['device_id'] = $device['device_id']; $device_perf['timestamp'] = array('NOW()'); if (can_ping_device($attribs) === true && is_array($device_perf)) { dbInsert($device_perf, 'device_perf'); } $device['pingable'] = $ping_response['result']; $ping_time = $ping_response['last_ping_timetaken']; $response = array(); $status_reason = ''; if ($device['pingable']) { $device['snmpable'] = isSNMPable($device); if ($device['snmpable']) { $status = '1'; $response['status_reason'] = ''; } else { echo 'SNMP Unreachable'; $status = '0'; $response['status_reason'] = 'snmp'; } } else { echo 'Unpingable'; $status = '0'; $response['status_reason'] = 'icmp'; } if ($device['status'] != $status) { $poll_update .= $poll_separator . "`status` = '{$status}'"; $poll_separator = ', '; dbUpdate(array('status' => $status, 'status_reason' => $response['status_reason']), 'devices', 'device_id=?', array($device['device_id'])); dbInsert(array('importance' => '0', 'device_id' => $device['device_id'], 'message' => 'Device is ' . ($status == '1' ? 'up' : 'down')), 'alerts'); log_event('Device status changed to ' . ($status == '1' ? 'Up' : 'Down'), $device, $status == '1' ? 'up' : 'down'); } if ($status == '1') { $graphs = array(); $oldgraphs = array(); if ($options['m']) { foreach (explode(',', $options['m']) as $module) { if (is_file('includes/polling/' . $module . '.inc.php')) { include 'includes/polling/' . $module . '.inc.php'; } } } else { foreach ($config['poller_modules'] as $module => $module_status) { if ($attribs['poll_' . $module] || $module_status && !isset($attribs['poll_' . $module])) { // TODO per-module polling stats include 'includes/polling/' . $module . '.inc.php'; } else { if (isset($attribs['poll_' . $module]) && $attribs['poll_' . $module] == '0') { echo "Module [ {$module} ] disabled on host.\n"; } else { echo "Module [ {$module} ] disabled globally.\n"; } } } } //end if if (!$options['m']) { // FIXME EVENTLOGGING -- MAKE IT SO WE DO THIS PER-MODULE? // This code cycles through the graphs already known in the database and the ones we've defined as being polled here // If there any don't match, they're added/deleted from the database. // Ideally we should hold graphs for xx days/weeks/polls so that we don't needlessly hide information. foreach (dbFetch('SELECT `graph` FROM `device_graphs` WHERE `device_id` = ?', array($device['device_id'])) as $graph) { if (isset($graphs[$graph['graph']])) { $oldgraphs[$graph['graph']] = true; } else { dbDelete('device_graphs', '`device_id` = ? AND `graph` = ?', array($device['device_id'], $graph['graph'])); } } foreach ($graphs as $graph => $value) { if (!isset($oldgraphs[$graph])) { echo '+'; dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph), 'device_graphs'); } echo $graph . ' '; } } //end if $device_end = utime(); $device_run = $device_end - $device_start; $device_time = substr($device_run, 0, 5); // TODO: These should be easy converts to rrd_create_update() // Poller performance rrd $poller_rrd = $config['rrd_dir'] . '/' . $device['hostname'] . '/poller-perf.rrd'; if (!is_file($poller_rrd)) { rrdtool_create($poller_rrd, 'DS:poller:GAUGE:600:0:U ' . $config['rrd_rra']); } if (!empty($device_time)) { $fields = array('poller' => $device_time); rrdtool_update($poller_rrd, $fields); } // Ping response rrd if (can_ping_device($attribs) === true) { $ping_rrd = $config['rrd_dir'] . '/' . $device['hostname'] . '/ping-perf.rrd'; if (!is_file($ping_rrd)) { rrdtool_create($ping_rrd, 'DS:ping:GAUGE:600:0:65535 ' . $config['rrd_rra']); } if (!empty($ping_time)) { $fields = array('ping' => $ping_time); rrdtool_update($ping_rrd, $fields); } $update_array['last_ping'] = array('NOW()'); $update_array['last_ping_timetaken'] = $ping_time; } $update_array['last_polled'] = array('NOW()'); $update_array['last_polled_timetaken'] = $device_time; // echo("$device_end - $device_start; $device_time $device_run"); echo "Polled in {$device_time} seconds\n"; d_echo('Updating ' . $device['hostname'] . "\n"); d_echo($update_array); $updated = dbUpdate($update_array, 'devices', '`device_id` = ?', array($device['device_id'])); if ($updated) { echo "UPDATED!\n"; } unset($storage_cache); // Clear cache of hrStorage ** MAYBE FIXME? ** unset($cache); // Clear cache (unify all things here?) } //end if }
function add_device($host, $snmpver = array(), $port = 161, $transport = 'udp', $error = FALSE) { global $config; // If $error set as TRUE break recursive function execute if ($error) { return FALSE; } // Reset snmp timeout and retries options for speedup device adding unset($config['snmp']['timeout'], $config['snmp']['retries']); $host = trim($host); list($hostshort) = explode(".", $host); // Test if host exists in database if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `hostname` = ?", array($host)) == '0') { $transport = strtolower($transport); $try_a = !($transport == 'udp6' || $transport == 'tcp6'); // Use IPv6 only if transport 'udp6' or 'tcp6' // Test DNS lookup. $ip = gethostbyname6($host, $try_a); if ($ip) { $ip_version = get_ip_version($ip); // Test reachability if (isPingable($host)) { // Test directory exists in /rrd/ if (!$config['rrd_override'] && file_exists($config['rrd_dir'] . '/' . $host)) { print_error("Directory <observium>/rrd/{$host} already exists."); return FALSE; } // Detect snmp transport if (stripos($transport, 'tcp') !== FALSE) { $transport = $ip_version == 4 ? 'tcp' : 'tcp6'; } else { $transport = $ip_version == 4 ? 'udp' : 'udp6'; } // Detect snmp port if (!is_numeric($port) || $port < 1 || $port > 65535) { $port = 161; } else { $port = (int) $port; } // Detect snmp version if (empty($snmpver)) { // Here set default snmp version order $i = 1; $snmpver_order = array(); foreach (array('v2c', 'v3', 'v1') as $snmpver) { if ($config['snmp']['version'] == $snmpver) { $snmpver_order[0] = $snmpver; } else { $snmpver_order[$i] = $snmpver; } $i++; } ksort($snmpver_order); foreach ($snmpver_order as $snmpver) { $ret = add_device($host, $snmpver, $port, $transport, $error); if ($ret === FALSE) { $error = TRUE; } elseif (is_numeric($ret) && $ret > 0) { return $ret; } } } if ($snmpver === "v3") { // Try each set of parameters from config foreach ($config['snmp']['v3'] as $v3) { $device = deviceArray($host, NULL, $snmpver, $port, $transport, $v3); print_message("Trying v3 parameters " . $v3['authname'] . "/" . $v3['authlevel'] . " ... "); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { $device_id = createHost($host, NULL, $snmpver, $port, $transport, $v3); return $device_id; } } else { print_warning("No reply on credentials " . $v3['authname'] . "/" . $v3['authlevel'] . " using {$snmpver}."); } } } elseif ($snmpver === "v2c" || $snmpver === "v1") { // Try each community from config foreach ($config['snmp']['community'] as $community) { $device = deviceArray($host, $community, $snmpver, $port, $transport); print_message("Trying {$snmpver} community {$community} ..."); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { $device_id = createHost($host, $community, $snmpver, $port, $transport); return $device_id; } } else { print_warning("No reply on community {$community} using {$snmpver}."); } } } else { print_error("Unsupported SNMP Version \"{$snmpver}\"."); } if (!$device_id) { // Failed SNMP print_error("Could not reach {$host} with given SNMP parameters using {$snmpver}."); } } else { // failed Reachability print_error("Could not ping {$host}."); } } else { // Failed DNS lookup print_error("Could not resolve {$host}."); } } else { // found in database print_error("Already got device {$host}."); } return FALSE; }
function discover_new_device($hostname, $source = 'xdp', $protocol = NULL, $device = NULL, $snmp_port = 161) { global $config; $source = strtolower($source); // Check if source is enabled for autodiscovery if ($config['autodiscovery'][$source]) { $flags = OBS_DNS_ALL; if (!$protocol) { $protocol = strtoupper($source); } print_cli_data("Try discovering host", "{$hostname} through {$protocol}", 3); // By first detect hostname is IP or domain name (IPv4/6 == 4/6, hostname == FALSE) $ip_version = get_ip_version($hostname); if ($ip_version) { // Hostname is IPv4/IPv6 $use_ip = TRUE; $ip = $hostname; } else { $use_ip = FALSE; // Add "mydomain" configuration if this resolves, converts switch1 -> switch1.mydomain.com if (!empty($config['mydomain']) && isDomainResolves($hostname . '.' . $config['mydomain'], $flags)) { $hostname .= '.' . $config['mydomain']; } // Determine v4 vs v6 $ip = gethostbyname6($hostname, $flags); if ($ip) { $ip_version = get_ip_version($ip); print_debug("Host {$hostname} resolved as {$ip}"); } else { // No DNS records print_debug("Host {$hostname} not resolved, autodiscovery fails."); return FALSE; } } if ($ip_version == 6) { $flags = $flags ^ OBS_DNS_A; // Exclude IPv4 } if (isset($config['autodiscovery']['ping_skip']) && $config['autodiscovery']['ping_skip']) { $flags = $flags | OBS_PING_SKIP; // Add skip pings flag } if (match_network($ip, $config['autodiscovery']['ip_nets'])) { print_debug("Host {$hostname} ({$ip}) founded inside configured nets, trying to add:"); // By first check if pingable $pingable = isPingable($ip, $flags); if (!$pingable && (isset($config['autodiscovery']['ping_skip']) && $config['autodiscovery']['ping_skip'])) { $flags = $flags | OBS_PING_SKIP; // Add skip pings flag if allowed in config $pingable = TRUE; } if ($pingable) { // Check if device duplicated by IP $ip = $ip_version == 4 ? $ip : Net_IPv6::uncompress($ip, TRUE); $db = dbFetchRow('SELECT D.`hostname` FROM ipv' . $ip_version . '_addresses AS A LEFT JOIN `ports` AS P ON A.`port_id` = P.`port_id` LEFT JOIN `devices` AS D ON D.`device_id` = P.`device_id` WHERE D.`disabled` = 0 AND A.`ipv' . $ip_version . '_address` = ?', array($ip)); if ($db) { print_debug('Already have device ' . $db['hostname'] . " with IP {$ip}"); return FALSE; } // Detect snmp transport, net-snmp needs udp6 for ipv6 $snmp_transport = $ip_version == 4 ? 'udp' : 'udp6'; $new_device = detect_device_snmpauth($ip, $snmp_port, $snmp_transport); if ($new_device) { if ($use_ip) { // Detect FQDN hostname // by sysName $snmphost = snmp_get($new_device, 'sysName.0', '-Oqv', 'SNMPv2-MIB'); if ($snmphost) { $snmp_ip = gethostbyname6($snmphost, $flags); } if ($snmp_ip == $ip) { $hostname = $snmphost; } else { // by PTR $ptr = gethostbyaddr6($ip); if ($ptr) { $ptr_ip = gethostbyname6($ptr, $flags); } if ($ptr && $ptr_ip == $ip) { $hostname = $ptr; } else { if ($config['autodiscovery']['require_hostname']) { print_debug("Device IP {$ip} does not seem to have FQDN."); return FALSE; } else { $hostname = $ip_version == 4 ? $ip : Net_IPv6::compress($hostname, TRUE); // Always use compressed IPv6 name } } } print_debug("Device IP {$ip} linked to FQDN name: {$hostname}"); } $new_device['hostname'] = $hostname; if (!check_device_duplicated($new_device)) { $snmp_v3 = array(); if ($new_device['snmp_version'] === 'v3') { $snmp_v3['snmp_authlevel'] = $new_device['snmp_authlevel']; $snmp_v3['snmp_authname'] = $new_device['snmp_authname']; $snmp_v3['snmp_authpass'] = $new_device['snmp_authpass']; $snmp_v3['snmp_authalgo'] = $new_device['snmp_authalgo']; $snmp_v3['snmp_cryptopass'] = $new_device['snmp_cryptopass']; $snmp_v3['snmp_cryptoalgo'] = $new_device['snmp_cryptoalgo']; } $remote_device_id = createHost($new_device['hostname'], $new_device['snmp_community'], $new_device['snmp_version'], $new_device['snmp_port'], $new_device['snmp_transport'], $snmp_v3); if ($remote_device_id) { if (is_flag_set(OBS_PING_SKIP, $flags)) { set_entity_attrib('device', $remote_device_id, 'ping_skip', 1); } $remote_device = device_by_id_cache($remote_device_id, 1); if ($port) { humanize_port($port); log_event("Device autodiscovered through {$protocol} on " . $device['hostname'] . " (port " . $port['port_label'] . ")", $remote_device_id, 'port', $port['port_id']); } else { log_event("Device autodiscovered through {$protocol} on " . $device['hostname'], $remote_device_id, $protocol); } //array_push($GLOBALS['devices'], $remote_device); // createHost() already puth this return $remote_device_id; } } } } } else { print_debug("IP {$ip} ({$hostname}) not permitted inside \$config['autodiscovery']['ip_nets'] in config.php"); } print_debug('Autodiscovery for host ' . $hostname . ' failed.'); } else { print_debug('Autodiscovery for protocol ' . $protocol . ' disabled.'); } return FALSE; }
function poll_device($device, $options) { global $config, $device, $polled_devices, $db_stats, $exec_status, $alert_rules, $alert_table, $graphs, $attribs; $alert_metrics = array(); $oid_cache = array(); $old_device_state = unserialize($device['device_state']); $attribs = get_entity_attribs('device', $device['device_id']); $pid_info = check_process_run($device); // This just clear stalled DB entries add_process_info($device); // Store process info $alert_rules = cache_alert_rules(); $alert_table = cache_device_alert_table($device['device_id']); if (OBS_DEBUG > 1 && (count($alert_rules) || count($alert_table))) { print_vars($alert_rules); print_vars($alert_table); } $status = 0; $device_start = utime(); // Start counting device poll time print_cli_heading($device['hostname'] . " [" . $device['device_id'] . "]", 1); print_cli_data("OS", $device['os'], 1); if ($config['os'][$device['os']]['group']) { $device['os_group'] = $config['os'][$device['os']]['group']; print_cli_data("OS Group", $device['os_group'], 1); } if (is_numeric($device['last_polled_timetaken'])) { print_cli_data("Last poll duration", $device['last_polled_timetaken'] . " seconds", 1); } print_cli_data("Last Polled", $device['last_polled'], 1); print_cli_data("SNMP Version", $device['snmp_version'], 1); //unset($poll_update); unset($poll_update_query); unset($poll_separator); $update_array = array(); $host_rrd_dir = $config['rrd_dir'] . "/" . $device['hostname']; if (!is_dir($host_rrd_dir)) { mkdir($host_rrd_dir); echo "Created directory : {$host_rrd_dir}\n"; } $flags = OBS_DNS_ALL; if ($device['snmp_transport'] == 'udp6' || $device['snmp_transport'] == 'tcp6') { $flags = $flags ^ OBS_DNS_A; } $attribs['ping_skip'] = isset($attribs['ping_skip']) && $attribs['ping_skip']; if ($attribs['ping_skip']) { $flags = $flags | OBS_PING_SKIP; // Add skip ping flag } $device['pingable'] = isPingable($device['hostname'], $flags); if ($device['pingable']) { $device['snmpable'] = isSNMPable($device); if ($device['snmpable']) { $ping_msg = $attribs['ping_skip'] ? '' : 'PING (' . $device['pingable'] . 'ms) and '; print_cli_data("Device status", "Device is reachable by " . $ping_msg . "SNMP (" . $device['snmpable'] . "ms)", 1); $status = "1"; $status_type = ''; } else { print_cli_data("Device status", "Device is not responding to SNMP requests", 1); $status = "0"; $status_type = 'snmp'; } } else { print_cli_data("Device status", "Device is not responding to PINGs", 1); $status = "0"; $status_type = 'ping'; } if ($device['status'] != $status) { dbUpdate(array('status' => $status), 'devices', 'device_id = ?', array($device['device_id'])); // dbInsert(array('importance' => '0', 'device_id' => $device['device_id'], 'message' => "Device is " .($status == '1' ? 'up' : 'down')), 'alerts'); $event_msg = 'Device status changed to '; if ($status == '1') { // Device Up, Severity Warning (4) $event_msg .= 'Up'; $event_severity = 4; } else { // Device Down, Severity Error (3)! $event_msg .= 'Down'; $event_severity = 3; } if ($status_type != '') { $event_msg .= ' (' . $status_type . ')'; } log_event($event_msg, $device, 'device', $device['device_id'], $event_severity); } rrdtool_update_ng($device, 'status', array('status' => $status)); if (!$attribs['ping_skip']) { // Ping response RRD database. rrdtool_update_ng($device, 'ping', array('ping' => $device['pingable'] ? $device['pingable'] : 'U')); } // SNMP response RRD database. rrdtool_update_ng($device, 'ping_snmp', array('ping_snmp' => $device['snmpable'] ? $device['snmpable'] : 'U')); $alert_metrics['device_status'] = $status; $alert_metrics['device_status_type'] = $status_type; $alert_metrics['device_ping'] = $device['pingable']; // FIXME, when ping skipped, here always 0.001 $alert_metrics['device_snmp'] = $device['snmpable']; if ($status == "1") { // Arrays for store and check enabled/disabled graphs $graphs = array(); $graphs_db = array(); foreach (dbFetchRows("SELECT * FROM `device_graphs` WHERE `device_id` = ?", array($device['device_id'])) as $entry) { $graphs_db[$entry['graph']] = isset($entry['enabled']) ? (bool) $entry['enabled'] : TRUE; } if (!$attribs['ping_skip']) { // Enable Ping graphs $graphs['ping'] = TRUE; } // Enable SNMP graphs $graphs['ping_snmp'] = TRUE; // Run these base modules always and before all other modules! $poll_modules = array('system', 'os'); $mods_disabled_global = array(); $mods_disabled_device = array(); $mods_excluded = array(); if ($options['m']) { foreach (explode(',', $options['m']) as $module) { $module = trim($module); if (in_array($module, $poll_modules)) { continue; } // Skip already added modules if ($module == 'unix-agent') { array_unshift($poll_modules, $module); // Add 'unix-agent' before all continue; } if (is_file($config['install_dir'] . "/includes/polling/{$module}.inc.php")) { $poll_modules[] = $module; } } } else { foreach ($config['poller_modules'] as $module => $module_status) { if (in_array($module, $poll_modules)) { continue; } // Skip already added modules if ($attribs['poll_' . $module] || $module_status && !isset($attribs['poll_' . $module])) { if (poller_module_excluded($device, $module)) { $mods_excluded[] = $module; //print_warning("Module [ $module ] excluded for device."); continue; } if ($module == 'unix-agent') { array_unshift($poll_modules, $module); // Add 'unix-agent' before all continue; } if (is_file($config['install_dir'] . "/includes/polling/{$module}.inc.php")) { $poll_modules[] = $module; } } elseif (isset($attribs['poll_' . $module]) && !$attribs['poll_' . $module]) { $mods_disabled_device[] = $module; //print_warning("Module [ $module ] disabled on device."); } else { $mods_disabled_global[] = $module; //print_warning("Module [ $module ] disabled globally."); } } } if (count($mods_excluded)) { print_cli_data("Modules Excluded", implode(", ", $mods_excluded), 1); } if (count($mods_disabled_global)) { print_cli_data("Disabled Globally", implode(", ", $mods_disabled_global), 1); } if (count($mods_disabled_device)) { print_cli_data("Disabled Device", implode(", ", $mods_disabled_global), 1); } if (count($poll_modules)) { print_cli_data("Modules Enabled", implode(", ", $poll_modules), 1); } echo PHP_EOL; foreach ($poll_modules as $module) { print_debug(PHP_EOL . "including: includes/polling/{$module}.inc.php"); print_cli_heading("Module Start: %R" . $module . ""); $m_start = utime(); include $config['install_dir'] . "/includes/polling/{$module}.inc.php"; $m_end = utime(); $m_run = round($m_end - $m_start, 4); $device_state['poller_mod_perf'][$module] = $m_run; print_cli_data("Module time", number_format($m_run, 4) . "s"); echo PHP_EOL; } print_cli_heading($device['hostname'] . " [" . $device['device_id'] . "] completed poller modules at " . date("Y-m-d H:i:s"), 1); // Check and update graphs DB $graphs_stat = array(); if (!isset($options['m'])) { // Hardcoded poller performance $graphs['poller_perf'] = TRUE; // Delete not exists graphs from DB (only if poller run without modules option) foreach ($graphs_db as $graph => $value) { if (!isset($graphs[$graph])) { dbDelete('device_graphs', "`device_id` = ? AND `graph` = ?", array($device['device_id'], $graph)); unset($graphs_db[$graph]); $graphs_stat['deleted'][] = $graph; } } } // Add or update graphs in DB foreach ($graphs as $graph => $value) { if (!isset($graphs_db[$graph])) { dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph, 'enabled' => $value), 'device_graphs'); $graphs_stat['added'][] = $graph; } else { if ($value != $graphs_db[$graph]) { dbUpdate(array('enabled' => $value), 'device_graphs', '`device_id` = ? AND `graph` = ?', array($device['device_id'], $graph)); $graphs_stat['updated'][] = $graph; } else { $graphs_stat['checked'][] = $graph; } } } // Print graphs stats foreach ($graphs_stat as $key => $stat) { if (count($stat)) { print_cli_data('Graphs [' . $key . ']', implode(', ', $stat), 1); } } $device_end = utime(); $device_run = $device_end - $device_start; $device_time = round($device_run, 4); $update_array['last_polled'] = array('NOW()'); $update_array['last_polled_timetaken'] = $device_time; $update_array['device_state'] = serialize($device_state); #echo("$device_end - $device_start; $device_time $device_run"); print_cli_data("Poller time", $device_time . " seconds", 1); //print_message(PHP_EOL."Polled in $device_time seconds"); // Only store performance data if we're not doing a single-module poll if (!$options['m']) { dbInsert(array('device_id' => $device['device_id'], 'operation' => 'poll', 'start' => $device_start, 'duration' => $device_run), 'devices_perftimes'); rrdtool_update_ng($device, 'perf-poller', array('val' => $device_time)); } if (OBS_DEBUG) { echo "Updating " . $device['hostname'] . " - "; print_vars($update_array); echo " \n"; } $updated = dbUpdate($update_array, 'devices', '`device_id` = ?', array($device['device_id'])); if ($updated) { print_cli_data("Updated Data", implode(", ", array_keys($update_array)), 1); } $alert_metrics['device_uptime'] = $device['uptime']; $alert_metrics['device_rebooted'] = $rebooted; // 0 - not rebooted, 1 - rebooted $alert_metrics['device_duration_poll'] = $device['last_polled_timetaken']; unset($cache_storage); // Clear cache of hrStorage ** MAYBE FIXME? ** (ok, later) unset($cache); // Clear cache (unify all things here?) } check_entity('device', $device, $alert_metrics); echo PHP_EOL; // Clean del_process_info($device); // Remove process info unset($alert_metrics); }
function add_device($hostname, $snmp_version = array(), $snmp_port = 161, $snmp_transport = 'udp', $options = array(), $flags = OBS_DNS_ALL) { global $config; // If $options['break'] set as TRUE, break recursive function execute if (isset($options['break']) && $options['break']) { return FALSE; } $return = FALSE; // By default return FALSE // Reset snmp timeout and retries options for speedup device adding unset($config['snmp']['timeout'], $config['snmp']['retries']); $snmp_transport = strtolower($snmp_transport); $hostname = strtolower(trim($hostname)); // Try detect if hostname is IP switch (get_ip_version($hostname)) { case 6: $hostname = Net_IPv6::compress($hostname, TRUE); // Always use compressed IPv6 name // Always use compressed IPv6 name case 4: if ($config['require_hostname']) { print_error("Hostname should be a valid resolvable FQDN name. Or set config option \$config['require_hostname'] as FALSE."); return $return; } $ip = $hostname; break; default: if ($snmp_transport == 'udp6' || $snmp_transport == 'tcp6') { $flags = $flags ^ OBS_DNS_A; // exclude A } // Test DNS lookup. $ip = gethostbyname6($hostname, $flags); } // Test if host exists in database if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `hostname` = ?", array($hostname)) == '0') { if ($ip) { $ip_version = get_ip_version($ip); // Test reachability $options['ping_skip'] = isset($options['ping_skip']) && $options['ping_skip']; if ($options['ping_skip']) { $flags = $flags | OBS_PING_SKIP; } if (isPingable($hostname, $flags)) { // Test directory exists in /rrd/ if (!$config['rrd_override'] && file_exists($config['rrd_dir'] . '/' . $hostname)) { print_error("Directory <observium>/rrd/{$hostname} already exists."); return FALSE; } // Detect snmp transport if (stripos($snmp_transport, 'tcp') !== FALSE) { $snmp_transport = $ip_version == 4 ? 'tcp' : 'tcp6'; } else { $snmp_transport = $ip_version == 4 ? 'udp' : 'udp6'; } // Detect snmp port if (!is_numeric($snmp_port) || $snmp_port < 1 || $snmp_port > 65535) { $snmp_port = 161; } else { $snmp_port = (int) $snmp_port; } // Detect snmp version if (empty($snmp_version)) { // Here set default snmp version order $i = 1; $snmp_version_order = array(); foreach (array('v2c', 'v3', 'v1') as $tmp_version) { if ($config['snmp']['version'] == $tmp_version) { $snmp_version_order[0] = $tmp_version; } else { $snmp_version_order[$i] = $tmp_version; } $i++; } ksort($snmp_version_order); foreach ($snmp_version_order as $tmp_version) { $ret = add_device($hostname, $tmp_version, $snmp_port, $snmp_transport, $options); if ($ret === FALSE) { // Set $options['break'] for break recursive $options['break'] = TRUE; } else { if (is_numeric($ret) && $ret != 0) { return $ret; } } } } else { if ($snmp_version === "v3") { // Try each set of parameters from config foreach ($config['snmp']['v3'] as $snmp_v3) { $device = build_initial_device_array($hostname, NULL, $snmp_version, $snmp_port, $snmp_transport, $snmp_v3); print_message("Trying v3 parameters " . $device['snmp_authname'] . "/" . $device['snmp_authlevel'] . " ... "); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { if (isset($options['test']) && $options['test']) { print_message('%WDevice "' . $hostname . '" has successfully been tested and available by ' . strtoupper($snmp_transport) . ' transport with SNMP ' . $snmp_version . ' credentials.%n', 'color'); $device_id = -1; } else { $device_id = createHost($hostname, NULL, $snmp_version, $snmp_port, $snmp_transport, $snmp_v3); if ($options['ping_skip']) { set_entity_attrib('device', $device_id, 'ping_skip', 1); // Force pingable check if (isPingable($hostname, $flags ^ OBS_PING_SKIP)) { print_warning("You passed option for skip device is pingable checks, but device available by ismp echo. Check device preferences."); } } } return $device_id; } } else { print_warning("No reply on credentials " . $device['snmp_authname'] . "/" . $device['snmp_authlevel'] . " using {$snmp_version}."); } } } else { if ($snmp_version === "v2c" || $snmp_version === "v1") { // Try each community from config foreach ($config['snmp']['community'] as $snmp_community) { $device = build_initial_device_array($hostname, $snmp_community, $snmp_version, $snmp_port, $snmp_transport); print_message("Trying {$snmp_version} community {$snmp_community} ..."); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { if (isset($options['test']) && $options['test']) { print_message('%WDevice "' . $hostname . '" has successfully been tested and available by ' . strtoupper($snmp_transport) . ' transport with SNMP ' . $snmp_version . ' credentials.%n', 'color'); $device_id = -1; } else { $device_id = createHost($hostname, $snmp_community, $snmp_version, $snmp_port, $snmp_transport); if ($options['ping_skip']) { set_entity_attrib('device', $device_id, 'ping_skip', 1); // Force pingable check if (isPingable($hostname, $flags ^ OBS_PING_SKIP)) { print_warning("You passed option for skip device is pingable checks, but device available by ismp echo. Check device preferences."); } } } return $device_id; } } else { print_warning("No reply on community {$snmp_community} using {$snmp_version}."); $return = 0; // Return zero for continue trying next auth } } } else { print_error("Unsupported SNMP Version \"{$snmp_version}\"."); $return = 0; // Return zero for continue trying next auth } } } if (!$device_id) { // Failed SNMP print_error("Could not reach {$hostname} with given SNMP parameters using {$snmp_version}."); $return = 0; // Return zero for continue trying next auth } } else { // failed Reachability print_error("Could not ping {$hostname}."); } } else { // Failed DNS lookup print_error("Could not resolve {$hostname}."); } } else { // found in database print_error("Already got device {$hostname}."); } return $return; }
function poll_device($device, $options) { global $config, $debug, $device, $polled_devices, $db_stats, $memcache, $exec_status, $alert_rules, $alert_table; $oid_cache = array(); $old_device_state = unserialize($device['device_state']); $attribs = get_dev_attribs($device['device_id']); $alert_rules = cache_alert_rules(); $alert_table = cache_device_alert_table($device['device_id']); if ($debug && (count($alert_rules) || count($alert_table))) { print_vars($alert_rules); print_vars($alert_table); } $status = 0; unset($array); $device_start = utime(); // Start counting device poll time echo $device['hostname'] . " " . $device['device_id'] . " " . $device['os'] . " "; if ($config['os'][$device['os']]['group']) { $device['os_group'] = $config['os'][$device['os']]['group']; echo "(" . $device['os_group'] . ")"; } echo "\n"; unset($poll_update); unset($poll_update_query); unset($poll_separator); $poll_update_array = array(); $host_rrd = $config['rrd_dir'] . "/" . $device['hostname']; if (!is_dir($host_rrd)) { mkdir($host_rrd); echo "Created directory : {$host_rrd}\n"; } $device['pingable'] = isPingable($device['hostname']); if ($device['pingable']) { $device['snmpable'] = isSNMPable($device); if ($device['snmpable']) { $status = "1"; $status_type = ''; } else { echo "SNMP Unreachable"; $status = "0"; $status_type = ' (snmp)'; } } else { echo "Unpingable"; $status = "0"; $status_type = ' (ping)'; } if ($device['status'] != $status) { $poll_update .= $poll_separator . "`status` = '{$status}'"; $poll_separator = ", "; dbUpdate(array('status' => $status), 'devices', 'device_id=?', array($device['device_id'])); dbInsert(array('importance' => '0', 'device_id' => $device['device_id'], 'message' => "Device is " . ($status == '1' ? 'up' : 'down')), 'alerts'); log_event('Device status changed to ' . ($status == '1' ? 'Up' : 'Down') . $status_type, $device, 'system'); notify($device, "Device " . ($status == '1' ? 'Up' : 'Down') . ": " . $device['hostname'] . $status_type, "Device " . ($status == '1' ? 'up' : 'down') . ": " . $device['hostname']); } $rrd = $config['rrd_dir'] . "/" . $device['hostname'] . "/status.rrd"; if (!is_file($rrd)) { rrdtool_create($rrd, "DS:status:GAUGE:600:0:1 "); } if ($status == "1" || $status == "0") { rrdtool_update($rrd, "N:" . $status); } else { rrdtool_update($rrd, "N:U"); } // Ping response RRD database. $ping_rrd = $config['rrd_dir'] . '/' . $device['hostname'] . '/ping.rrd'; if (!is_file($ping_rrd)) { rrdtool_create($ping_rrd, "DS:ping:GAUGE:600:0:65535 "); } if ($device['pingable']) { rrdtool_update($ping_rrd, "N:" . $device['pingable']); } else { rrdtool_update($ping_rrd, "N:U"); } // SNMP response RRD database. $ping_snmp_rrd = $config['rrd_dir'] . '/' . $device['hostname'] . '/ping_snmp.rrd'; if (!is_file($ping_snmp_rrd)) { rrdtool_create($ping_snmp_rrd, "DS:ping_snmp:GAUGE:600:0:65535 "); } if ($device['snmpable']) { rrdtool_update($ping_snmp_rrd, "N:" . $device['snmpable']); } else { rrdtool_update($ping_snmp_rrd, "N:U"); } if ($status == "1") { $graphs = array(); $oldgraphs = array(); // Enable Ping graphs $graphs['ping'] = TRUE; // Enable SNMP graphs $graphs['ping_snmp'] = TRUE; // Run this base modules always and before all other modules! $poll_modules = array('system', 'os'); if ($options['m']) { foreach (explode(',', $options['m']) as $module) { $module = trim($module); if (in_array($module, $poll_modules)) { continue; } // Skip already added modules if ($module == 'unix-agent') { array_unshift($poll_modules, $module); // Add 'unix-agent' before all continue; } if (is_file($config['install_dir'] . "/includes/polling/{$module}.inc.php")) { $poll_modules[] = $module; } } } else { foreach ($config['poller_modules'] as $module => $module_status) { if (in_array($module, $poll_modules)) { continue; } // Skip already added modules if ($attribs['poll_' . $module] || $module_status && !isset($attribs['poll_' . $module])) { if (poller_module_excluded($device, $module)) { print_warning("Module [ {$module} ] excluded for device."); continue; } if ($module == 'unix-agent') { array_unshift($poll_modules, $module); // Add 'unix-agent' before all continue; } if (is_file($config['install_dir'] . "/includes/polling/{$module}.inc.php")) { $poll_modules[] = $module; } } elseif (isset($attribs['poll_' . $module]) && !$attribs['poll_' . $module]) { print_warning("Module [ {$module} ] disabled on device."); } else { print_warning("Module [ {$module} ] disabled globally."); } } } foreach ($poll_modules as $module) { print_debug(PHP_EOL . "including: includes/polling/{$module}.inc.php"); $m_start = utime(); include $config['install_dir'] . "/includes/polling/{$module}.inc.php"; $m_end = utime(); $m_run = round($m_end - $m_start, 4); $device_state['poller_mod_perf'][$module] = number_format($m_run, 4); print_message("Module time: {$m_run}" . "s"); } // Fields to notify about in event log - FIXME should move to definitions? $update_fields = array('version', 'features', 'hardware', 'serial', 'kernel', 'distro', 'distro_ver', 'arch', 'asset_tag', 'icon'); // Log changed variables foreach ($update_fields as $field) { if (isset(${$field}) && ${$field} != $device[$field]) { $update_array[$field] = ${$field}; log_event(ucfirst($field) . " -> " . $update_array[$field], $device, 'system'); } } if (!isset($options['m'])) { // FIXME EVENTLOGGING -- MAKE IT SO WE DO THIS PER-MODULE? // This code cycles through the graphs already known in the database and the ones we've defined as being polled here // If there any don't match, they're added/deleted from the database. // Ideally we should hold graphs for xx days/weeks/polls so that we don't needlessly hide information. // Hardcoded poller performance $graphs['poller_perf'] = TRUE; foreach (dbFetch("SELECT `graph` FROM `device_graphs` WHERE `device_id` = ?", array($device['device_id'])) as $graph) { if (!isset($graphs[$graph["graph"]])) { dbDelete('device_graphs', "`device_id` = ? AND `graph` = ?", array($device['device_id'], $graph["graph"])); } else { $oldgraphs[$graph["graph"]] = TRUE; } } foreach ($graphs as $graph => $value) { if (!isset($oldgraphs[$graph])) { echo "+"; dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph), 'device_graphs'); } echo $graph . " "; } } $device_end = utime(); $device_run = $device_end - $device_start; $device_time = round($device_run, 4); $update_array['last_polled'] = array('NOW()'); $update_array['last_polled_timetaken'] = $device_time; $update_array['device_state'] = serialize($device_state); #echo("$device_end - $device_start; $device_time $device_run"); echo "Polled in {$device_time} seconds\n"; // Only store performance data if we're not doing a single-module poll if (!$options['m']) { dbInsert(array('device_id' => $device['device_id'], 'operation' => 'poll', 'start' => $device_start, 'duration' => $device_run), 'devices_perftimes'); $poller_rrd = $config['rrd_dir'] . "/" . $device['hostname'] . "/perf-poller.rrd"; if (!is_file($poller_rrd)) { rrdtool_create($poller_rrd, "DS:val:GAUGE:600:0:38400 "); } rrdtool_update($poller_rrd, "N:" . $device_time); } if ($debug) { echo "Updating " . $device['hostname'] . " - "; print_vars($update_array); echo " \n"; } $updated = dbUpdate($update_array, 'devices', '`device_id` = ?', array($device['device_id'])); if ($updated) { echo "UPDATED!\n"; } unset($cache_storage); // Clear cache of hrStorage ** MAYBE FIXME? ** (ok, later) unset($cache); // Clear cache (unify all things here?) } }
function poll_device($device, $options) { global $config, $device, $polled_devices, $db_stats, $memcache, $exec_status, $alert_rules, $alert_table, $graphs, $attribs; $alert_metrics = array(); $oid_cache = array(); $old_device_state = unserialize($device['device_state']); $attribs = get_dev_attribs($device['device_id']); $alert_rules = cache_alert_rules(); $alert_table = cache_device_alert_table($device['device_id']); if (OBS_DEBUG > 1 && (count($alert_rules) || count($alert_table))) { print_vars($alert_rules); print_vars($alert_table); } $status = 0; unset($array); $device_start = utime(); // Start counting device poll time echo $device['hostname'] . " " . $device['device_id'] . " " . $device['os'] . " "; if ($config['os'][$device['os']]['group']) { $device['os_group'] = $config['os'][$device['os']]['group']; echo "(" . $device['os_group'] . ")"; } echo "\n"; unset($poll_update); unset($poll_update_query); unset($poll_separator); $poll_update_array = array(); $host_rrd_dir = $config['rrd_dir'] . "/" . $device['hostname']; if (!is_dir($host_rrd_dir)) { mkdir($host_rrd_dir); echo "创建的目录 : {$host_rrd_dir}\n"; } $try_a = !($device['snmp_transport'] == 'udp6' || $device['snmp_transport'] == 'tcp6'); // Use IPv6 only if transport 'udp6' or 'tcp6' $device['pingable'] = isPingable($device['hostname'], $try_a); if ($device['pingable']) { $device['snmpable'] = isSNMPable($device); if ($device['snmpable']) { $status = "1"; $status_type = ''; } else { echo "SNMP 无法访问"; $status = "0"; $status_type = 'snmp'; } } else { echo "Unpingable"; $status = "0"; $status_type = 'ping'; } if ($device['status'] != $status) { $poll_update .= $poll_separator . "`status` = '{$status}'"; $poll_separator = ", "; dbUpdate(array('status' => $status), 'devices', 'device_id = ?', array($device['device_id'])); dbInsert(array('importance' => '0', 'device_id' => $device['device_id'], 'message' => "设备的 " . ($status == '1' ? 'up' : 'down')), 'alerts'); $event_msg = '设备状态变更为 '; if ($status == '1') { // Device Up, Severity Warning (4) $event_msg .= 'Up'; $event_severity = 4; } else { // Device Down, Severity Error (3)! $event_msg .= 'Down'; $event_severity = 3; } if ($status_type != '') { $event_msg .= ' (' . $status_type . ')'; } log_event($event_msg, $device, 'device', $device['device_id'], $event_severity); } $rrd_filename = "status.rrd"; rrdtool_create($device, $rrd_filename, "DS:status:GAUGE:600:0:1 "); if ($status == "1" || $status == "0") { rrdtool_update($device, $rrd_filename, "N:" . $status); } else { rrdtool_update($device, $rrd_filename, "N:U"); } // Ping response RRD database. $ping_rrd = 'ping.rrd'; rrdtool_create($device, $ping_rrd, "DS:ping:GAUGE:600:0:65535 "); if ($device['pingable']) { rrdtool_update($device, $ping_rrd, "N:" . $device['pingable']); } else { rrdtool_update($device, $ping_rrd, "N:U"); } // SNMP response RRD database. $ping_snmp_rrd = 'ping_snmp.rrd'; rrdtool_create($device, $ping_snmp_rrd, "DS:ping_snmp:GAUGE:600:0:65535 "); if ($device['snmpable']) { rrdtool_update($device, $ping_snmp_rrd, "N:" . $device['snmpable']); } else { rrdtool_update($device, $ping_snmp_rrd, "N:U"); } $alert_metrics['device_status'] = $status; $alert_metrics['device_status_type'] = $status_type; $alert_metrics['device_ping'] = $device['pingable']; $alert_metrics['device_snmp'] = $device['snmpable']; if ($status == "1") { // Arrays for store and check enabled/disabled graphs $graphs = array(); $graphs_db = array(); foreach (dbFetchRows("SELECT * FROM `device_graphs` WHERE `device_id` = ?", array($device['device_id'])) as $entry) { $graphs_db[$entry['graph']] = isset($entry['enabled']) ? (bool) $entry['enabled'] : TRUE; } // Enable Ping graphs $graphs['ping'] = TRUE; // Enable SNMP graphs $graphs['ping_snmp'] = TRUE; // Run these base modules always and before all other modules! $poll_modules = array('system', 'os'); if ($options['m']) { foreach (explode(',', $options['m']) as $module) { $module = trim($module); if (in_array($module, $poll_modules)) { continue; } // Skip already added modules if ($module == 'unix-agent') { array_unshift($poll_modules, $module); // Add 'unix-agent' before all continue; } if (is_file($config['install_dir'] . "/includes/polling/{$module}.inc.php")) { $poll_modules[] = $module; } } } else { foreach ($config['poller_modules'] as $module => $module_status) { if (in_array($module, $poll_modules)) { continue; } // Skip already added modules if ($attribs['poll_' . $module] || $module_status && !isset($attribs['poll_' . $module])) { if (poller_module_excluded($device, $module)) { print_warning("模块 [ {$module} ] 排除设备."); continue; } if ($module == 'unix-agent') { array_unshift($poll_modules, $module); // Add 'unix-agent' before all continue; } if (is_file($config['install_dir'] . "/includes/polling/{$module}.inc.php")) { $poll_modules[] = $module; } } elseif (isset($attribs['poll_' . $module]) && !$attribs['poll_' . $module]) { print_warning("模块 [ {$module} ] 禁用设备."); } else { print_warning("模块 [ {$module} ] 禁用全局."); } } } foreach ($poll_modules as $module) { print_debug(PHP_EOL . "including: includes/polling/{$module}.inc.php"); $m_start = utime(); include $config['install_dir'] . "/includes/polling/{$module}.inc.php"; $m_end = utime(); $m_run = round($m_end - $m_start, 4); $device_state['poller_mod_perf'][$module] = number_format($m_run, 4); print_message("Module [ {$module} ] time: {$m_run}" . "s"); } // Fields to notify about in event log - FIXME should move to definitions? $update_fields = array('version', 'features', 'hardware', 'serial', 'kernel', 'distro', 'distro_ver', 'arch', 'asset_tag'); // Log changed variables foreach ($update_fields as $field) { if (isset(${$field}) && ${$field} != $device[$field]) { $update_array[$field] = ${$field}; log_event(ucfirst($field) . " -> " . $update_array[$field], $device, 'device', $device['device_id']); } } // Here additional fields, change only if not set already foreach (array('type', 'icon') as $field) { if (isset(${$field}) && ($device[$field] == "unknown" || $device[$field] == '')) { $update_array[$field] = ${$field}; log_event(ucfirst($field) . " -> " . $update_array[$field], $device, 'device', $device['device_id']); } } // Check and update graphs DB $graphs_stat = array(); if (!isset($options['m'])) { // Hardcoded poller performance $graphs['poller_perf'] = TRUE; // Delete not exists graphs from DB (only if poller run without modules option) foreach ($graphs_db as $graph => $value) { if (!isset($graphs[$graph])) { dbDelete('device_graphs', "`device_id` = ? AND `graph` = ?", array($device['device_id'], $graph)); unset($graphs_db[$graph]); $graphs_stat['deleted'][] = $graph; } } } // Add or update graphs in DB foreach ($graphs as $graph => $value) { if (!isset($graphs_db[$graph])) { dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph, 'enabled' => $value), 'device_graphs'); $graphs_stat['added'][] = $graph; } else { if ($value != $graphs_db[$graph]) { dbUpdate(array('enabled' => $value), 'device_graphs', '`device_id` = ? AND `graph` = ?', array($device['device_id'], $graph)); $graphs_stat['updated'][] = $graph; } else { $graphs_stat['checked'][] = $graph; } } } // Print graphs stats foreach ($graphs_stat as $key => $stat) { if (count($stat)) { echo ' Graphs [' . $key . ']: ' . implode(', ', $stat) . PHP_EOL; } } $device_end = utime(); $device_run = $device_end - $device_start; $device_time = round($device_run, 4); $update_array['last_polled'] = array('NOW()'); $update_array['last_polled_timetaken'] = $device_time; $update_array['device_state'] = serialize($device_state); #echo("$device_end - $device_start; $device_time $device_run"); print_message(PHP_EOL . "Polled in {$device_time} seconds"); // Only store performance data if we're not doing a single-module poll if (!$options['m']) { dbInsert(array('device_id' => $device['device_id'], 'operation' => 'poll', 'start' => $device_start, 'duration' => $device_run), 'devices_perftimes'); $poller_rrd = "perf-poller.rrd"; rrdtool_create($device, $poller_rrd, "DS:val:GAUGE:600:0:38400 "); rrdtool_update($device, $poller_rrd, "N:" . $device_time); } if (OBS_DEBUG) { echo "更新 " . $device['hostname'] . " - "; print_vars($update_array); echo " \n"; } $updated = dbUpdate($update_array, 'devices', '`device_id` = ?', array($device['device_id'])); if ($updated) { echo "已更新!\n"; } $alert_metrics['device_uptime'] = $device['uptime']; $alert_metrics['device_rebooted'] = $rebooted; // 0 - not rebooted, 1 - rebooted $alert_metrics['device_duration_poll'] = $device['last_polled_timetaken']; unset($cache_storage); // Clear cache of hrStorage ** MAYBE FIXME? ** (ok, later) unset($cache); // Clear cache (unify all things here?) } check_entity('device', $device, $alert_metrics); unset($alert_metrics); }
echo "DEBUG!\n"; $debug = 1; } $i = 0; $device_query = mysql_query("SELECT * FROM `devices` WHERE `ignore` = '0' AND `disabled` = '0' AND `status` = '1' {$where} ORDER BY device_id DESC"); while ($device = mysql_fetch_array($device_query)) { echo "-> " . $device['hostname'] . "\n"; $device_start = utime(); // Start counting device poll time $host_rrd = $config['rrd_dir'] . "/" . $device['hostname']; if (!is_dir($host_rrd)) { mkdir($host_rrd); echo "Created directory : {$host_rrd}\n"; } $i++; $device['pingable'] = isPingable($device['hostname']); if ($device['pingable']) { $device['snmpable'] = isSNMPable($device['hostname'], $device['community'], $device['snmpver'], $device['port']); } if ($device['pingable'] && $device['snmpable']) { // Reachability Check if ($options['t']) { include "includes/polling/" . $options['t'] . ".inc.php"; } else { include "includes/polling/ports.inc.php"; include "includes/polling/ports-etherlike.inc.php"; include "includes/polling/cisco-mac-accounting.inc.php"; } } else { echo " Unreachable"; }
function discover_new_device($hostname, $source = 'xdp', $protocol = NULL, $device = NULL, $snmp_port = 161) { global $config; $source = strtolower($source); if ($config['autodiscovery'][$source]) { if (!$protocol) { $protocol = strtoupper($source); } print_message("发现新主机 {$hostname} 通过 {$protocol}"); // By first detect hostname is IP or domain name (IPv4/6 == 4/6, hostname == FALSE) $ip_version = get_ip_version($hostname); if ($ip_version) { // Hostname is IPv4/IPv6 $use_ip = TRUE; $ip = $hostname; } else { $use_ip = FALSE; if (!empty($config['mydomain']) && isDomainResolves($hostname . '.' . $config['mydomain'])) { $hostname .= '.' . $config['mydomain']; } $ip = gethostbyname6($hostname); if ($ip) { $ip_version = get_ip_version($ip); print_debug("主机 {$hostname} 解析为 {$ip}"); } else { // No DNS records print_debug("主机 {$hostname} 无法解析, 自动发现失败."); return FALSE; } } if (match_network($ip, $config['autodiscovery']['ip_nets'])) { print_debug("主机 {$hostname} ({$ip}) 内部网络创建配置, 尝试增加:"); if (isPingable($ip)) { // Check if device duplicated by IP $ip = $ip_version == 4 ? $ip : Net_IPv6::uncompress($ip, TRUE); $db = dbFetchRow('SELECT D.`hostname` FROM ipv' . $ip_version . '_addresses AS A LEFT JOIN `ports` AS P ON A.`port_id` = P.`port_id` LEFT JOIN `devices` AS D ON D.`device_id` = P.`device_id` WHERE D.`disabled` = 0 AND A.`ipv' . $ip_version . '_address` = ?', array($ip)); if ($db) { print_debug('已经有设备 ' . $db['hostname'] . " 包含 {$ip}"); return FALSE; } // Detect snmp transport $snmp_transport = $ip_version == 4 ? 'udp' : 'udp6'; $new_device = detect_device_snmpauth($ip, $snmp_port, $snmp_transport); if ($new_device) { if ($use_ip) { // Detect FQDN hostname // by sysName $snmphost = snmp_get($new_device, "sysName.0", "-Oqv", "SNMPv2-MIB", mib_dirs()); if ($snmphost) { $snmp_ip = gethostbyname6($snmphost); } if ($snmp_ip == $ip) { $hostname = $snmphost; } else { // by PTR $ptr = gethostbyaddr6($ip); if ($ptr) { $ptr_ip = gethostbyname6($ptr); } if ($ptr && $ptr_ip == $ip) { $hostname = $ptr; } else { print_debug("设备 IP {$ip} 没有 FQDN 名称"); return FALSE; } } print_debug("设备 IP {$ip} 发现 FQDN 名称: {$hostname}"); } $new_device['hostname'] = $hostname; if (!check_device_duplicated($new_device)) { $snmp_v3 = array(); if ($new_device['snmp_version'] === 'v3') { $snmp_v3['snmp_authlevel'] = $new_device['snmp_authlevel']; $snmp_v3['snmp_authname'] = $new_device['snmp_authname']; $snmp_v3['snmp_authpass'] = $new_device['snmp_authpass']; $snmp_v3['snmp_authalgo'] = $new_device['snmp_authalgo']; $snmp_v3['snmp_cryptopass'] = $new_device['snmp_cryptopass']; $snmp_v3['snmp_cryptoalgo'] = $new_device['snmp_cryptoalgo']; } $remote_device_id = createHost($new_device['hostname'], $new_device['snmp_community'], $new_device['snmp_version'], $new_device['snmp_port'], $new_device['snmp_transport'], $snmp_v3); if ($remote_device_id) { $remote_device = device_by_id_cache($remote_device_id, 1); if ($port) { humanize_port($port); log_event("设备自动发现通过 {$protocol} 在 " . $device['hostname'] . " (port " . $port['label'] . ")", $remote_device_id, 'port', $port['port_id']); } else { log_event("设备自动发现通过 {$protocol} 在 " . $device['hostname'], $remote_device_id, $protocol); } //array_push($GLOBALS['devices'], $remote_device); // createHost() already puth this return $remote_device_id; } } } } } else { print_debug("IP {$ip} ({$hostname}) 不允许内部 \$config['autodiscovery']['ip_nets'] 位于 config.php"); } print_debug('自动发现主机 ' . $hostname . ' 错误.'); } else { print_debug('自动发现协议 ' . $protocol . ' 禁用.'); } return FALSE; }
function addHost($host, $community, $snmpver, $port = 161) { global $config; list($hostshort) = explode(".", $host); if (isDomainResolves($host)) { if (isPingable($host)) { if (mysql_result(mysql_query("SELECT COUNT(*) FROM `devices` WHERE `hostname` = '{$host}'"), 0) == '0') { $snmphost = shell_exec($config['snmpget'] . " -m SNMPv2-MIB -Oqv -{$snmpver} -c {$community} {$host}:{$port} sysName.0"); if ($snmphost == $host || ($hostshort = $host)) { createHost($host, $community, $snmpver, $port); } else { echo "Given hostname does not match SNMP-read hostname!\n"; } } else { echo "Already got host {$host}\n"; } } else { echo "Could not ping {$host}\n"; } } else { echo "Could not resolve {$host}\n"; } }
/** * @dataProvider providerIsPingable * @group network */ public function testIsPingable($result, $hostname, $try_a = TRUE) { $flags = OBS_DNS_ALL; if (!$try_a) { $flags = $flags ^ OBS_DNS_A; } $ping = isPingable($hostname, $flags); $ping = is_numeric($ping) && $ping > 0; // Function return random float number $this->assertSame($result, $ping); }
function addHost($host, $snmpver, $port = '161', $transport = 'udp', $quiet = '0') { global $config; list($hostshort) = explode(".", $host); // Test Database Exists if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `hostname` = ?", array($host)) == '0') { // Test if IP or Hostname if (!inet_pton($host)) { // Test reachability if (isPingable($host)) { $added = 0; if (empty($snmpver)) { // Try SNMPv2c $snmpver = 'v2c'; $ret = addHost($host, $snmpver); if (!$ret) { //Try SNMPv3 $snmpver = 'v3'; $ret = addHost($host, $snmpver); if (!$ret) { // Try SNMPv1 $snmpver = 'v1'; return addHost($host, $snmpver); } else { return $ret; } } else { return $ret; } } if ($snmpver === "v3") { // Try each set of parameters from config foreach ($config['snmp']['v3'] as $v3) { $device = deviceArray($host, NULL, $snmpver, $port, $transport, $v3); if ($quiet == '0') { print_message("Trying v3 parameters " . $v3['authname'] . "/" . $v3['authlevel'] . " ... "); } if (isSNMPable($device)) { $snmphost = snmp_get($device, "sysName.0", "-Oqv", "SNMPv2-MIB"); if (empty($snmphost) or $snmphost == $host || ($hostshort = $host)) { $device_id = createHost($host, NULL, $snmpver, $port, $transport, $v3); return $device_id; } else { if ($quiet == '0') { print_error("Given hostname does not match SNMP-read hostname ({$snmphost})!"); } } } else { if ($quiet == '0') { print_error("No reply on credentials " . $v3['authname'] . "/" . $v3['authlevel'] . " using {$snmpver}"); } } } } elseif ($snmpver === "v2c" or $snmpver === "v1") { // try each community from config foreach ($config['snmp']['community'] as $community) { $device = deviceArray($host, $community, $snmpver, $port, $transport, NULL); if ($quiet == '0') { print_message("Trying community {$community} ..."); } if (isSNMPable($device)) { $snmphost = snmp_get($device, "sysName.0", "-Oqv", "SNMPv2-MIB"); if ($snmphost == "" || $snmphost && ($snmphost == $host || ($hostshort = $host))) { $device_id = createHost($host, $community, $snmpver, $port, $transport); return $device_id; } else { if ($quiet == '0') { print_error("Given hostname does not match SNMP-read hostname ({$snmphost})!"); } } } else { if ($quiet == '0') { print_error("No reply on community {$community} using {$snmpver}"); } } } } else { if ($quiet == '0') { print_error("Unsupported SNMP Version \"{$snmpver}\"."); } } if (!$device_id) { // Failed SNMP if ($quiet == '0') { print_error("Could not reach {$host} with given SNMP community using {$snmpver}"); } } } else { // failed Reachability if ($quiet == '0') { print_error("Could not ping {$host}"); } } } else { // Failed DNS lookup if ($quiet == '0') { print_error("{$host} looks like an IP address, please use FQDN"); } } } else { // found in database if ($quiet == '0') { print_error("Already got host {$host}"); } } return 0; }
function poll_device($device, $options) { global $config, $debug, $device, $polled_devices, $db_stats, $memcache; $old_device_state = unserialize($device['device_state']); $attribs = get_dev_attribs($device['device_id']); $status = 0; unset($array); $device_start = utime(); // Start counting device poll time echo $device['hostname'] . " " . $device['device_id'] . " " . $device['os'] . " "; if ($config['os'][$device['os']]['group']) { $device['os_group'] = $config['os'][$device['os']]['group']; echo "(" . $device['os_group'] . ")"; } echo "\n"; unset($poll_update); unset($poll_update_query); unset($poll_separator); $poll_update_array = array(); $host_rrd = $config['rrd_dir'] . "/" . $device['hostname']; if (!is_dir($host_rrd)) { mkdir($host_rrd); echo "Created directory : {$host_rrd}\n"; } $device['pingable'] = isPingable($device['hostname']); if ($device['pingable']) { $device['snmpable'] = isSNMPable($device); if ($device['snmpable']) { $status = "1"; $status_type = ''; } else { echo "SNMP Unreachable"; $status = "0"; $status_type = ' (snmp)'; } } else { echo "Unpingable"; $status = "0"; $status_type = ' (ping)'; } if ($device['status'] != $status) { $poll_update .= $poll_separator . "`status` = '{$status}'"; $poll_separator = ", "; dbUpdate(array('status' => $status), 'devices', 'device_id=?', array($device['device_id'])); dbInsert(array('importance' => '0', 'device_id' => $device['device_id'], 'message' => "Device is " . ($status == '1' ? 'up' : 'down')), 'alerts'); log_event('Device status changed to ' . ($status == '1' ? 'Up' : 'Down') . $status_type, $device, 'system'); notify($device, "Device " . ($status == '1' ? 'Up' : 'Down') . ": " . $device['hostname'] . $status_type, "Device " . ($status == '1' ? 'up' : 'down') . ": " . $device['hostname']); } $rrd = $config['rrd_dir'] . "/" . $device['hostname'] . "/status.rrd"; if (!is_file($rrd)) { rrdtool_create($rrd, "DS:status:GAUGE:600:0:1 " . $config['rrd_rra']); } if ($status == "1" || $status == "0") { rrdtool_update($rrd, "N:" . $status); } else { rrdtool_update($rrd, "N:U"); } // Ping response RRD database. $ping_rrd = $config['rrd_dir'] . '/' . $device['hostname'] . '/ping.rrd'; if (!is_file($ping_rrd)) { rrdtool_create($ping_rrd, "DS:ping:GAUGE:600:0:65535 " . $config['rrd_rra']); } if ($device['pingable']) { rrdtool_update($ping_rrd, "N:" . $device['pingable']); } else { rrdtool_update($ping_rrd, "N:U"); } // SNMP response RRD database. $ping_snmp_rrd = $config['rrd_dir'] . '/' . $device['hostname'] . '/ping_snmp.rrd'; if (!is_file($ping_snmp_rrd)) { rrdtool_create($ping_snmp_rrd, "DS:ping_snmp:GAUGE:600:0:65535 " . $config['rrd_rra']); } if ($device['snmpable']) { rrdtool_update($ping_snmp_rrd, "N:" . $device['snmpable']); } else { rrdtool_update($ping_snmp_rrd, "N:U"); } if ($status == "1") { $graphs = array(); $oldgraphs = array(); // Enable Ping graphs $graphs['ping'] = TRUE; // Enable SNMP graphs $graphs['ping_snmp'] = TRUE; if ($options['m']) { foreach (explode(",", $options['m']) as $module) { if (is_file("includes/polling/" . $module . ".inc.php")) { include "includes/polling/" . $module . ".inc.php"; } } } else { foreach ($config['poller_modules'] as $module => $module_status) { if ($attribs['poll_' . $module] || $module_status && !isset($attribs['poll_' . $module])) { if ($debug) { echo "including: includes/polling/{$module}.inc.php\n"; } include 'includes/polling/' . $module . '.inc.php'; } elseif (isset($attribs['poll_' . $module]) && $attribs['poll_' . $module] == "0") { echo "Module [ {$module} ] disabled on host.\n"; } else { echo "Module [ {$module} ] disabled globally.\n"; } } } if (!isset($options['m'])) { // FIXME EVENTLOGGING -- MAKE IT SO WE DO THIS PER-MODULE? // This code cycles through the graphs already known in the database and the ones we've defined as being polled here // If there any don't match, they're added/deleted from the database. // Ideally we should hold graphs for xx days/weeks/polls so that we don't needlessly hide information. // Hardcoded poller performance $graphs['poller_perf'] = TRUE; foreach (dbFetch("SELECT `graph` FROM `device_graphs` WHERE `device_id` = ?", array($device['device_id'])) as $graph) { if (!isset($graphs[$graph["graph"]])) { dbDelete('device_graphs', "`device_id` = ? AND `graph` = ?", array($device['device_id'], $graph["graph"])); } else { $oldgraphs[$graph["graph"]] = TRUE; } } foreach ($graphs as $graph => $value) { if (!isset($oldgraphs[$graph])) { echo "+"; dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph), 'device_graphs'); } echo $graph . " "; } } $device_end = utime(); $device_run = $device_end - $device_start; $device_time = substr($device_run, 0, 5); $update_array['last_polled'] = array('NOW()'); $update_array['last_polled_timetaken'] = $device_time; $update_array['device_state'] = serialize($device_state); #echo("$device_end - $device_start; $device_time $device_run"); echo "Polled in {$device_time} seconds\n"; // Only store performance data if we're not doing a single-module poll if (!$options['m']) { dbInsert(array('device_id' => $device['device_id'], 'operation' => 'poll', 'start' => $device_start, 'duration' => $device_run), 'devices_perftimes'); $poller_rrd = $config['rrd_dir'] . "/" . $device['hostname'] . "/perf-poller.rrd"; if (!is_file($poller_rrd)) { rrdtool_create($poller_rrd, "DS:val:GAUGE:600:0:38400 " . $config['rrd_rra']); } rrdtool_update($poller_rrd, "N:" . $device_time); } if ($debug) { echo "Updating " . $device['hostname'] . " - " . print_r($update_array) . " \n"; } $updated = dbUpdate($update_array, 'devices', '`device_id` = ?', array($device['device_id'])); if ($updated) { echo "UPDATED!\n"; } unset($storage_cache); // Clear cache of hrStorage ** MAYBE FIXME? ** unset($cache); // Clear cache (unify all things here?) } }
function perform_snmp_scan($net, $force_network, $force_broadcast) { global $stats, $config, $debug, $vdebug; echo 'Range: ' . $net->network . '/' . $net->bitmask . PHP_EOL; $config['snmp']['timeout'] = 1; $config['snmp']['retries'] = 0; $config['fping_options']['retries'] = 0; $start = ip2long($net->network); $end = ip2long($net->broadcast) - 1; if ($force_network === true) { //Force-scan network address d_echo("Forcing network address scan" . PHP_EOL); $start = $start - 1; } if ($force_broadcast === true) { //Force-scan broadcast address d_echo("Forcing broadcast address scan" . PHP_EOL); $end = $end + 1; } if ($net->bitmask === "31") { //Handle RFC3021 /31 prefixes $start = ip2long($net->network) - 1; $end = ip2long($net->broadcast); d_echo("RFC3021 network, hosts " . long2ip($start + 1) . " and " . long2ip($end) . PHP_EOL . PHP_EOL); } elseif ($net->bitmask === "32") { //Handle single-host /32 prefixes $start = ip2long($net->network) - 1; $end = $start + 1; d_echo("RFC3021 network, hosts " . long2ip($start + 1) . " and " . long2ip($end) . PHP_EOL . PHP_EOL); } else { d_echo("Network: " . $net->network . PHP_EOL); d_echo("Broadcast: " . $net->broadcast . PHP_EOL . PHP_EOL); } while ($start++ < $end) { $stats['count']++; $host = long2ip($start); if ($vdebug) { echo "Scanning: " . $host . PHP_EOL; } if (match_network($config['autodiscovery']['nets-exclude'], $host)) { if ($vdebug) { echo "Excluded by config.php" . PHP_EOL . PHP_EOL; } else { echo '|'; } continue; } $test = isPingable($host); if ($test['result'] === false) { if ($vdebug) { echo "Unpingable Device" . PHP_EOL . PHP_EOL; } else { echo '.'; } continue; } if (ip_exists($host)) { $stats['known']++; if ($vdebug) { echo "Known Device" . PHP_EOL; } else { echo '*'; } continue; } foreach (array('udp', 'tcp') as $transport) { try { addHost(gethostbyaddr($host), '', $config['snmp']['port'], $transport, $config['distributed_poller_group']); $stats['added']++; if ($vdebug) { echo "Added Device" . PHP_EOL . PHP_EOL; } else { echo '+'; } break; } catch (HostExistsException $e) { $stats['known']++; if ($vdebug) { echo "Known Device" . PHP_EOL . PHP_EOL; } else { echo '*'; } break; } catch (HostUnreachablePingException $e) { if ($vdebug) { echo "Unpingable Device" . PHP_EOL . PHP_EOL; } else { echo '.'; } break; } catch (HostUnreachableException $e) { if ($debug) { print_error($e->getMessage() . " over {$transport}"); foreach ($e->getReasons() as $reason) { echo " {$reason}" . PHP_EOL; } } if ($transport === 'tcp') { // tried both udp and tcp without success $stats['failed']++; if ($vdebug) { echo "Failed to Add Device" . PHP_EOL . PHP_EOL; } else { echo '-'; } } } } } echo PHP_EOL; }
/** * Add a device to LibreNMS * * @param string $host dns name or ip address * @param string $snmp_version If this is empty, try v2c,v3,v1. Otherwise, use this specific version. * @param string $port the port to connect to for snmp * @param string $transport udp or tcp * @param string $poller_group the poller group this device will belong to * @param boolean $force_add add even if the device isn't reachable * @param string $port_assoc_mode snmp field to use to determine unique ports * * @return int returns the device_id of the added device * * @throws HostExistsException This hostname already exists * @throws HostIpExistsException We already have a host with this IP * @throws HostUnreachableException We could not reach this device is some way * @throws HostUnreachablePingException We could not ping the device * @throws InvalidPortAssocModeException The given port association mode was invalid * @throws SnmpVersionUnsupportedException The given snmp version was invalid */ function addHost($host, $snmp_version = '', $port = '161', $transport = 'udp', $poller_group = '0', $force_add = false, $port_assoc_mode = 'ifIndex') { global $config; // Test Database Exists if (host_exists($host) === true) { throw new HostExistsException("Already have host {$host}"); } // Valid port assoc mode if (!is_valid_port_assoc_mode($port_assoc_mode)) { throw new InvalidPortAssocModeException("Invalid port association_mode '{$port_assoc_mode}'. Valid modes are: " . join(', ', get_port_assoc_modes())); } // check if we have the host by IP if ($config['addhost_alwayscheckip'] === true) { $ip = gethostbyname($host); } else { $ip = $host; } if (ip_exists($ip)) { throw new HostIpExistsException("Already have host with this IP {$host}"); } // Test reachability if (!$force_add) { $address_family = snmpTransportToAddressFamily($transport); $ping_result = isPingable($host, $address_family); if (!$ping_result['result']) { throw new HostUnreachablePingException("Could not ping {$host}"); } } // if $snmpver isn't set, try each version of snmp if (empty($snmp_version)) { $snmpvers = array('v2c', 'v3', 'v1'); } else { $snmpvers = array($snmp_version); } $host_unreachable_exception = new HostUnreachableException("Could not connect, please check the snmp details and snmp reachability"); // try different snmp variables to add the device foreach ($snmpvers as $snmpver) { if ($snmpver === "v3") { // Try each set of parameters from config foreach ($config['snmp']['v3'] as $v3) { $device = deviceArray($host, null, $snmpver, $port, $transport, $v3, $port_assoc_mode); if ($force_add === true || isSNMPable($device)) { if ($force_add !== true) { $snmphost = snmp_get($device, "sysName.0", "-Oqv", "SNMPv2-MIB"); } $result = createHost($host, null, $snmpver, $port, $transport, $v3, $poller_group, $port_assoc_mode, $snmphost, $force_add); if ($result !== false) { return $result; } } else { $host_unreachable_exception->addReason("SNMP {$snmpver}: No reply with credentials " . $v3['authname'] . "/" . $v3['authlevel']); } } } elseif ($snmpver === "v2c" || $snmpver === "v1") { // try each community from config foreach ($config['snmp']['community'] as $community) { $device = deviceArray($host, $community, $snmpver, $port, $transport, null, $port_assoc_mode); if ($force_add === true || isSNMPable($device)) { if ($force_add !== true) { $snmphost = snmp_get($device, "sysName.0", "-Oqv", "SNMPv2-MIB"); } $result = createHost($host, $community, $snmpver, $port, $transport, array(), $poller_group, $port_assoc_mode, $snmphost, $force_add); if ($result !== false) { return $result; } } else { $host_unreachable_exception->addReason("SNMP {$snmpver}: No reply with community {$community}"); } } } else { throw new SnmpVersionUnsupportedException("Unsupported SNMP Version \"{$snmpver}\", must be v1, v2c, or v3"); } } throw $host_unreachable_exception; }
function poll_device($device, $options) { global $config, $device, $polled_devices, $memcache; $attribs = get_dev_attribs($device['device_id']); $device['snmp_max_repeaters'] = $attribs['snmp_max_repeaters']; $device['snmp_max_oid'] = $attribs['snmp_max_oid']; $status = 0; unset($array); $device_start = microtime(true); // Start counting device poll time echo 'Hostname: ' . $device['hostname'] . PHP_EOL; echo 'Device ID: ' . $device['device_id'] . PHP_EOL; echo 'OS: ' . $device['os']; $ip = dnslookup($device); if (!empty($ip) && $ip != inet6_ntop($device['ip'])) { log_event('Device IP changed to ' . $ip, $device, 'system'); $db_ip = inet_pton($ip); dbUpdate(array('ip' => $db_ip), 'devices', 'device_id=?', array($device['device_id'])); } if ($config['os'][$device['os']]['group']) { $device['os_group'] = $config['os'][$device['os']]['group']; echo ' (' . $device['os_group'] . ')'; } echo PHP_EOL . PHP_EOL; unset($poll_update); unset($poll_update_query); unset($poll_separator); $poll_update_array = array(); $update_array = array(); $host_rrd = $config['rrd_dir'] . '/' . $device['hostname']; if ($config['norrd'] !== true && !is_dir($host_rrd)) { mkdir($host_rrd); echo "Created directory : {$host_rrd}\n"; } $address_family = snmpTransportToAddressFamily($device['transport']); $ping_response = isPingable($device['hostname'], $address_family, $attribs); $device_perf = $ping_response['db']; $device_perf['device_id'] = $device['device_id']; $device_perf['timestamp'] = array('NOW()'); if (can_ping_device($attribs) === true && is_array($device_perf)) { dbInsert($device_perf, 'device_perf'); } $device['pingable'] = $ping_response['result']; $ping_time = $ping_response['last_ping_timetaken']; $response = array(); $status_reason = ''; if ($device['pingable']) { $device['snmpable'] = isSNMPable($device); if ($device['snmpable']) { $status = '1'; $response['status_reason'] = ''; } else { echo 'SNMP Unreachable'; $status = '0'; $response['status_reason'] = 'snmp'; } } else { echo 'Unpingable'; $status = '0'; $response['status_reason'] = 'icmp'; } if ($device['status'] != $status) { $poll_update .= $poll_separator . "`status` = '{$status}'"; $poll_separator = ', '; dbUpdate(array('status' => $status, 'status_reason' => $response['status_reason']), 'devices', 'device_id=?', array($device['device_id'])); log_event('Device status changed to ' . ($status == '1' ? 'Up' : 'Down') . ' from ' . $response['status_reason'] . ' check.', $device, $status == '1' ? 'up' : 'down'); } if ($status == '1') { $graphs = array(); $oldgraphs = array(); // we always want the core module to be included include 'includes/polling/core.inc.php'; $force_module = false; if ($options['m']) { $config['poller_modules'] = array(); foreach (explode(',', $options['m']) as $module) { if (is_file('includes/polling/' . $module . '.inc.php')) { $config['poller_modules'][$module] = 1; $force_module = true; } } } foreach ($config['poller_modules'] as $module => $module_status) { $os_module_status = $config['os'][$device['os']]['poller_modules'][$module]; d_echo("Modules status: Global" . (isset($module_status) ? $module_status ? '+ ' : '- ' : ' ')); d_echo("OS" . (isset($os_module_status) ? $os_module_status ? '+ ' : '- ' : ' ')); d_echo("Device" . (isset($attribs['poll_' . $module]) ? $attribs['poll_' . $module] ? '+ ' : '- ' : ' ')); if ($force_module === true || $attribs['poll_' . $module] || $os_module_status && !isset($attribs['poll_' . $module]) || $module_status && !isset($os_module_status) && !isset($attribs['poll_' . $module])) { $module_start = 0; $module_time = 0; $module_start = microtime(true); echo "\n#### Load poller module {$module} ####\n"; include "includes/polling/{$module}.inc.php"; $module_time = microtime(true) - $module_start; printf("\n>> Runtime for poller module '%s': %.4f seconds\n", $module, $module_time); echo "#### Unload poller module {$module} ####\n\n"; // save per-module poller stats $tags = array('module' => $module, 'rrd_def' => 'DS:poller:GAUGE:600:0:U', 'rrd_name' => array('poller-perf', $module)); $fields = array('poller' => $module_time); data_update($device, 'poller-perf', $tags, $fields); // remove old rrd $oldrrd = rrd_name($device['hostname'], array('poller', $module, 'perf')); if (is_file($oldrrd)) { unlink($oldrrd); } } elseif (isset($attribs['poll_' . $module]) && $attribs['poll_' . $module] == '0') { echo "Module [ {$module} ] disabled on host.\n\n"; } elseif (isset($os_module_status) && $os_module_status == '0') { echo "Module [ {$module} ] disabled on os.\n\n"; } else { echo "Module [ {$module} ] disabled globally.\n\n"; } } // Update device_groups UpdateGroupsForDevice($device['device_id']); if (!isset($options['m'])) { // FIXME EVENTLOGGING -- MAKE IT SO WE DO THIS PER-MODULE? // This code cycles through the graphs already known in the database and the ones we've defined as being polled here // If there any don't match, they're added/deleted from the database. // Ideally we should hold graphs for xx days/weeks/polls so that we don't needlessly hide information. foreach (dbFetch('SELECT `graph` FROM `device_graphs` WHERE `device_id` = ?', array($device['device_id'])) as $graph) { if (isset($graphs[$graph['graph']])) { $oldgraphs[$graph['graph']] = true; } else { dbDelete('device_graphs', '`device_id` = ? AND `graph` = ?', array($device['device_id'], $graph['graph'])); } } foreach ($graphs as $graph => $value) { if (!isset($oldgraphs[$graph])) { echo '+'; dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph), 'device_graphs'); } echo $graph . ' '; } } //end if $device_end = microtime(true); $device_run = $device_end - $device_start; $device_time = substr($device_run, 0, 5); // Poller performance if (!empty($device_time)) { $tags = array('rrd_def' => 'DS:poller:GAUGE:600:0:U', 'module' => 'ALL'); $fields = array('poller' => $device_time); data_update($device, 'poller-perf', $tags, $fields); } // Ping response if (can_ping_device($attribs) === true && !empty($ping_time)) { $tags = array('rrd_def' => 'DS:ping:GAUGE:600:0:65535'); $fields = array('ping' => $ping_time); $update_array['last_ping'] = array('NOW()'); $update_array['last_ping_timetaken'] = $ping_time; data_update($device, 'ping-perf', $tags, $fields); } $update_array['last_polled'] = array('NOW()'); $update_array['last_polled_timetaken'] = $device_time; // echo("$device_end - $device_start; $device_time $device_run"); echo "Polled in {$device_time} seconds\n"; d_echo('Updating ' . $device['hostname'] . "\n"); $updated = dbUpdate($update_array, 'devices', '`device_id` = ?', array($device['device_id'])); if ($updated) { echo "UPDATED!\n"; } unset($storage_cache); // Clear cache of hrStorage ** MAYBE FIXME? ** unset($cache); // Clear cache (unify all things here?) } //end if }
function discover_new_device($hostname, $source = 'xdp', $protocol = NULL, $device = NULL, $port = 161) { global $config; $source = strtolower($source); if ($config['autodiscovery'][$source]) { if (!$protocol) { $protocol = strtoupper($source); } print_message("Discovering new host {$hostname} through {$protocol}"); // By first detect hostname is IP or domain name (IPv4/6 == 4/6, hostname == FALSE) $ip_version = get_ip_version($hostname); if ($ip_version) { // Hostname is IPv4/IPv6 $use_ip = TRUE; } else { $use_ip = FALSE; if (!empty($config['mydomain']) && isDomainResolves($hostname . '.' . $config['mydomain'])) { $hostname .= '.' . $config['mydomain']; } $ip = gethostbyname6($hostname); if ($ip) { $ip_version = get_ip_version($ip); print_debug("Host {$hostname} resolved as {$ip}"); } else { // No DNS records print_debug("Host {$hostname} not resolved, autodiscovery fails."); return FALSE; } } if (match_network($ip, $config['autodiscovery']['ip_nets'])) { print_debug("Host {$hostname} ({$ip}) founded inside configured nets, try to adding:"); if (isPingable($ip)) { // Check if device duplicated by IP $ip = $ip_version == 4 ? $hostname : Net_IPv6::uncompress($hostname, TRUE); $db = dbFetchRow('SELECT D.`hostname` FROM ipv' . $ip_version . '_addresses AS A LEFT JOIN `ports` AS P ON A.`port_id` = P.`port_id` LEFT JOIN `devices` AS D ON D.`device_id` = P.`device_id` WHERE D.`disabled` = 0 AND A.`ipv' . $ip_version . '_address` = ?', array($ip)); if ($db) { print_debug('Already have device ' . $db['hostname'] . " with {$ip}"); return FALSE; } // Detect snmp transport $transport = $ip_version == 4 ? 'udp' : 'udp6'; $new_device = detect_device_snmpauth($ip, $port, $transport); if ($new_device) { if ($use_ip) { // Detect FQDN hostname // by sysName $snmphost = snmp_get($new_device, "sysName.0", "-Oqv", "SNMPv2-MIB", mib_dirs()); if ($snmphost) { $snmp_ip = gethostbyname6($snmphost); } if ($snmp_ip == $ip) { $hostname = $snmphost; } else { // by PTR $ptr = gethostbyaddr6($ip); if ($ptr) { $ptr_ip = gethostbyname6($ptr); } if ($ptr && $ptr_ip == $ip) { $hostname = $ptr; } else { print_debug("Device IP {$ip} not have FQDN name"); return FALSE; } } print_debug("Device IP {$ip} founded FQDN name: {$hostname}"); } $new_device['hostname'] = $hostname; if (!check_device_duplicated($new_device)) { $v3 = array(); if ($new_device['snmpver'] === 'v3') { $v3['authlevel'] = $new_device['authlevel']; $v3['authname'] = $new_device['authname']; $v3['authpass'] = $new_device['authpass']; $v3['authalgo'] = $new_device['authalgo']; $v3['cryptopass'] = $new_device['cryptopass']; $v3['cryptoalgo'] = $new_device['cryptoalgo']; } $remote_device_id = createHost($new_device['hostname'], $new_device['community'], $new_device['snmpver'], $new_device['port'], $new_device['transport'], $v3); if ($remote_device_id) { $remote_device = device_by_id_cache($remote_device_id, 1); if ($port) { humanize_port($port); log_event("Device autodiscovered through {$protocol} on " . $device['hostname'] . " (port " . $port['label'] . ")", $remote_device_id, 'port', $port['port_id']); } else { log_event("Device autodiscovered through {$protocol} on " . $device['hostname'], $remote_device_id, $protocol); } //array_push($GLOBALS['devices'], $remote_device); // createHost() already puth this return $remote_device_id; } } } } } else { print_debug("IP {$ip} ({$hostname}) not permitted inside \$config['autodiscovery']['ip_nets'] in config.php"); } print_debug('Autodiscovery for host ' . $hostname . ' fails.'); } else { print_debug('Autodiscovery for protocol ' . $protocol . ' disabled.'); } return FALSE; }
function add_device($hostname, $snmp_version = array(), $snmp_port = 161, $snmp_transport = 'udp', $options = array()) { global $config; // If $options['break'] set as TRUE, break recursive function execute if (isset($options['break']) && $options['break']) { return FALSE; } $return = FALSE; // By default return FALSE // Reset snmp timeout and retries options for speedup device adding unset($config['snmp']['timeout'], $config['snmp']['retries']); $hostname = trim($hostname); list($hostshort) = explode(".", $hostname); // Test if host exists in database if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `hostname` = ?", array($hostname)) == '0') { $snmp_transport = strtolower($snmp_transport); $try_a = !($snmp_transport == 'udp6' || $snmp_transport == 'tcp6'); // Use IPv6 only if transport 'udp6' or 'tcp6' // Test DNS lookup. $ip = gethostbyname6($hostname, $try_a); if ($ip) { $ip_version = get_ip_version($ip); // Test reachability if (isPingable($hostname, $try_a)) { // Test directory exists in /rrd/ if (!$config['rrd_override'] && file_exists($config['rrd_dir'] . '/' . $hostname)) { print_error("Directory <observium>/rrd/{$hostname} already exists."); return FALSE; } // Detect snmp transport if (stripos($snmp_transport, 'tcp') !== FALSE) { $snmp_transport = $ip_version == 4 ? 'tcp' : 'tcp6'; } else { $snmp_transport = $ip_version == 4 ? 'udp' : 'udp6'; } // Detect snmp port if (!is_numeric($snmp_port) || $snmp_port < 1 || $snmp_port > 65535) { $snmp_port = 161; } else { $snmp_port = (int) $snmp_port; } // Detect snmp version if (empty($snmp_version)) { // Here set default snmp version order $i = 1; $snmp_version_order = array(); foreach (array('v2c', 'v3', 'v1') as $tmp_version) { if ($config['snmp']['version'] == $tmp_version) { $snmp_version_order[0] = $tmp_version; } else { $snmp_version_order[$i] = $tmp_version; } $i++; } ksort($snmp_version_order); foreach ($snmp_version_order as $tmp_version) { $ret = add_device($hostname, $tmp_version, $snmp_port, $snmp_transport, $options); if ($ret === FALSE) { // Set $options['break'] for break recursive $options['break'] = TRUE; } else { if (is_numeric($ret) && $ret != 0) { return $ret; } } } } else { if ($snmp_version === "v3") { // Try each set of parameters from config foreach ($config['snmp']['v3'] as $snmp_v3) { $device = build_initial_device_array($hostname, NULL, $snmp_version, $snmp_port, $snmp_transport, $snmp_v3); print_message("Trying v3 parameters " . $device['snmp_authname'] . "/" . $device['snmp_authlevel'] . " ... "); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { if (isset($options['test']) && $options['test']) { print_message('%WDevice "' . $hostname . '" has successfully been tested and available by ' . strtoupper($snmp_transport) . ' transport with SNMP ' . $snmp_version . ' credentials.%n', 'color'); $device_id = -1; } else { $device_id = createHost($hostname, NULL, $snmp_version, $snmp_port, $snmp_transport, $snmp_v3); } return $device_id; } } else { print_warning("No reply on credentials " . $device['snmp_authname'] . "/" . $device['snmp_authlevel'] . " using {$snmp_version}."); } } } else { if ($snmp_version === "v2c" || $snmp_version === "v1") { // Try each community from config foreach ($config['snmp']['community'] as $snmp_community) { $device = build_initial_device_array($hostname, $snmp_community, $snmp_version, $snmp_port, $snmp_transport); print_message("Trying {$snmp_version} community {$snmp_community} ..."); if (isSNMPable($device)) { if (!check_device_duplicated($device)) { if (isset($options['test']) && $options['test']) { print_message('%W设备 "' . $hostname . '" 已成功地测试和可用于 ' . strtoupper($snmp_transport) . ' transport with SNMP ' . $snmp_version . ' credentials.%n', 'color'); $device_id = -1; } else { $device_id = createHost($hostname, $snmp_community, $snmp_version, $snmp_port, $snmp_transport); } return $device_id; } } else { print_warning("No reply on community {$snmp_community} using {$snmp_version}."); $return = 0; // Return zero for continue trying next auth } } } else { print_error("Unsupported SNMP Version \"{$snmp_version}\"."); $return = 0; // Return zero for continue trying next auth } } } if (!$device_id) { // Failed SNMP print_error("无法到达主机 {$hostname} 使用给定的SNMP参数 {$snmp_version}."); $return = 0; // Return zero for continue trying next auth } } else { // failed Reachability print_error("无法 ping {$hostname}."); } } else { // Failed DNS lookup print_error("无法解析 {$hostname}."); } } else { // found in database print_error("已经发现设备 {$hostname}."); } return $return; }
$community = $argv[2]; $snmpver = strtolower($argv[3]); if (is_numeric($argv[4])) { $port = $argv[4]; } else { $port = 161; } if (!$snmpver) { $snmpver = "v2c"; } if (!$community) { $community = $config['community']; } list($hostshort) = explode(".", $host); if (isDomainResolves($argv[1])) { if (isPingable($argv[1])) { if (mysql_result(mysql_query("SELECT COUNT(*) FROM `devices` WHERE `hostname` = '" . mres($host) . "'"), 0) == '0') { $snmphost = trim(str_replace("\"", "", shell_exec($config['snmpget'] . " -m SNMPv2-MIB -Oqv -{$snmpver} -c {$community} {$host}:{$port} sysName.0"))); if ($snmphost && ($snmphost == $host || ($hostshort = $host))) { $return = createHost($host, $community, $snmpver, $port); if ($return) { echo $return . "\n"; } else { echo "Adding {$host} failed\n"; } } else { echo "Given hostname does not match SNMP-read hostname!\n"; } } else { echo "Already got host {$host}\n"; }
function addHost($host, $snmpver, $port = '161', $transport = 'udp', $quiet = '0', $poller_group = '0', $force_add = '0') { global $config; list($hostshort) = explode(".", $host); // Test Database Exists if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `hostname` = ?", array($host)) == '0') { if ($config['addhost_alwayscheckip'] === TRUE) { $ip = gethostbyname($host); } else { $ip = $host; } if (ip_exists($ip) === false) { // Test reachability if ($force_add == 1 || isPingable($host)) { if (empty($snmpver)) { // Try SNMPv2c $snmpver = 'v2c'; $ret = addHost($host, $snmpver, $port, $transport, $quiet, $poller_group, $force_add); if (!$ret) { //Try SNMPv3 $snmpver = 'v3'; $ret = addHost($host, $snmpver, $port, $transport, $quiet, $poller_group, $force_add); if (!$ret) { // Try SNMPv1 $snmpver = 'v1'; return addHost($host, $snmpver, $port, $transport, $quiet, $poller_group, $force_add); } else { return $ret; } } else { return $ret; } } if ($snmpver === "v3") { // Try each set of parameters from config foreach ($config['snmp']['v3'] as $v3) { $device = deviceArray($host, NULL, $snmpver, $port, $transport, $v3); if ($quiet == '0') { print_message("Trying v3 parameters " . $v3['authname'] . "/" . $v3['authlevel'] . " ... "); } if ($force_add == 1 || isSNMPable($device)) { $snmphost = snmp_get($device, "sysName.0", "-Oqv", "SNMPv2-MIB"); if (empty($snmphost) or $snmphost == $host || ($hostshort = $host)) { $device_id = createHost($host, NULL, $snmpver, $port, $transport, $v3, $poller_group); return $device_id; } else { if ($quiet == '0') { print_error("Given hostname does not match SNMP-read hostname ({$snmphost})!"); } } } else { if ($quiet == '0') { print_error("No reply on credentials " . $v3['authname'] . "/" . $v3['authlevel'] . " using {$snmpver}"); } } } } elseif ($snmpver === "v2c" or $snmpver === "v1") { // try each community from config foreach ($config['snmp']['community'] as $community) { $device = deviceArray($host, $community, $snmpver, $port, $transport, NULL); if ($quiet == '0') { print_message("Trying community {$community} ..."); } if ($force_add == 1 || isSNMPable($device)) { $snmphost = snmp_get($device, "sysName.0", "-Oqv", "SNMPv2-MIB"); if (empty($snmphost) || $snmphost && ($snmphost == $host || ($hostshort = $host))) { $device_id = createHost($host, $community, $snmpver, $port, $transport, array(), $poller_group); return $device_id; } else { if ($quiet == '0') { print_error("Given hostname does not match SNMP-read hostname ({$snmphost})!"); } } } else { if ($quiet == '0') { print_error("No reply on community {$community} using {$snmpver}"); } } } } else { if ($quiet == '0') { print_error("Unsupported SNMP Version \"{$snmpver}\"."); } } if (!$device_id) { // Failed SNMP if ($quiet == '0') { print_error("Could not reach {$host} with given SNMP community using {$snmpver}"); } } } else { // failed Reachability if ($quiet == '0') { print_error("Could not ping {$host}"); } } } else { if ($quiet == 0) { print_error("Already have host with this IP {$host}"); } } } else { // found in database if ($quiet == '0') { print_error("Already got host {$host}"); } } return 0; }
#!/usr/bin/env php <?php include "includes/defaults.inc.php"; include "config.php"; include "includes/functions.php"; $device_query = mysql_query("SELECT * FROM `devices` WHERE `device_id` LIKE '%" . $argv[1] . "' AND disabled = '0' ORDER BY `device_id` DESC"); while ($device = mysql_fetch_assoc($device_query)) { $port = $device['snmp_port']; echo $device['hostname'] . " "; if (isPingable($device['hostname'])) { $pos = snmp_get($device, "sysDescr.0", "-Oqv", "SNMPv2-MIB"); echo $device['protocol'] . ":" . $device['hostname'] . ":" . $device['snmp_port'] . " - " . $device['snmp_community'] . " " . $device['snmp_version'] . ": "; if ($pos == '') { $status = '0'; } else { $status = '1'; } } else { $status = '0'; } if ($status == '1') { echo "正常\n"; } else { echo "异常\n"; } if ($status != $device['status']) { mysql_query("UPDATE `devices` SET `status`= '{$status}' WHERE `device_id` = '" . $device['device_id'] . "'"); if ($status == '1') { $stat = "正常"; mysql_query("INSERT INTO alerts (importance, device_id, message) VALUES ('0', '" . $device['device_id'] . "', '设备正常\n')"); if ($config['alerts']['email']['enable']) {