1<?php 2 3/** 4 * Observium 5 * 6 * This file is part of Observium. 7 * 8 * @package observium 9 * @subpackage poller 10 * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited 11 * 12 */ 13 14 15/** 16 * Poll and cache entity _NUMERIC_ Oids, 17 * need for cross cache between different entities, ie status and sensors 18 * 19 * @param $device 20 * @param $entity_type 21 * @param $oid_cache 22 * 23 * @return bool 24 */ 25function poll_cache_oids($device, $entity_type, &$oid_cache) 26{ 27 global $config; 28 29 $use_walk = FALSE; // Use multi get by default 30 $mib_walk_option = $entity_type . '_walk'; // ie: $config['mibs'][$mib]['sensors_walk'] 31 $snmp_flags = OBS_SNMP_ALL_NUMERIC; // Numeric Oids by default 32 33 $translate = entity_type_translate_array($entity_type); 34 $table = $translate['table']; 35 $mib_field = $translate['mib_field']; 36 $object_field = $translate['object_field']; 37 $oid_field = $translate['oid_field']; 38 $deleted_field = $translate['deleted_field']; 39 $device_field = $translate['device_id_field']; 40 41 switch ($entity_type) 42 { 43 case 'sensor': 44 case 'status': 45 case 'counter': 46 // Device not support walk 47 $use_walk = isset($config['os'][$device['os']]['sensors_poller_walk']) && 48 $config['os'][$device['os']]['sensors_poller_walk']; 49 50 // For sensors and statuses always use same option 51 $mib_walk_option = 'sensors_walk'; 52 53 // Walk query 54 $walk_query = "SELECT DISTINCT `$mib_field`, `$object_field` FROM `$table` WHERE `$device_field` = ? AND `$deleted_field` = ? AND `poller_type` = ?"; 55 $walk_query .= " AND `$mib_field` != ? AND `$object_field` != ?"; 56 $walk_params = [$device['device_id'], '0', 'snmp', '', '']; 57 58 // Multi-get query 59 $get_query = "SELECT `$oid_field` FROM `$table` WHERE `$device_field` = ? AND `$deleted_field` = ? AND `poller_type` = ? ORDER BY `$oid_field`"; 60 $get_params = [$device['device_id'], '0', 'snmp']; 61 62 break; 63 64 default: 65 print_debug("Unknown Entity $entity_type"); 66 return FALSE; 67 } 68 69 if ($use_walk) 70 { 71 // Walk by mib & object 72 $oid_to_cache = dbFetchRows($walk_query, $walk_params); 73 print_debug_vars($oid_to_cache); 74 foreach ($oid_to_cache as $entry) 75 { 76 $mib = $entry[$mib_field]; 77 $object = $entry[$object_field]; 78 79 // MIB not support walk (by definition) 80 if (isset($config['mibs'][$mib][$mib_walk_option]) && 81 !$config['mibs'][$mib][$mib_walk_option]) 82 { 83 continue; 84 } 85 else if (isset($GLOBALS['cache']['snmp_object_polled'][$mib][$object])) 86 { 87 print_debug("MIB/Object ($mib::$object)already polled."); 88 continue; 89 } 90 91 $oid_cache = snmp_walk_multipart_oid($device, $object, $oid_cache, $mib, NULL, $snmp_flags); 92 $GLOBALS['cache']['snmp_object_polled'][$mib][$object] = 1; 93 } 94 } else { 95 // Multi get for all others 96 $oid_to_cache = dbFetchColumn($get_query, $get_params); 97 usort($oid_to_cache, 'compare_numeric_oids'); // correctly sort numeric oids 98 print_debug_vars($oid_to_cache); 99 $oid_cache = snmp_get_multi_oid($device, $oid_to_cache, $oid_cache, NULL, NULL, $snmp_flags); 100 } 101 102 print_debug_vars($oid_cache); 103 104 return TRUE; 105} 106 107function poll_device($device, $options) 108{ 109 global $config, $device, $polled_devices, $db_stats, $exec_status, $alert_rules, $alert_table, $graphs, $attribs; 110 111 $device_start = utime(); // Start counting device poll time 112 113 $alert_metrics = array(); 114 $oid_cache = array(); 115 $device_state = array(); 116 //$old_device_state = unserialize($device['device_state']); 117 $attribs = get_entity_attribs('device', $device['device_id']); 118 119 print_debug_vars($device); 120 print_debug_vars($attribs); 121 122 $pid_info = check_process_run($device); // This just clear stalled DB entries 123 add_process_info($device); // Store process info 124 125 $alert_rules = cache_alert_rules(); 126 $alert_table = cache_device_alert_table($device['device_id']); 127 128 print_debug_vars($alert_rules); 129 print_debug_vars($alert_table); 130 131 $status = 0; 132 133 print_cli_heading($device['hostname'] . " [".$device['device_id']."]", 1); 134 135 print_cli_data("OS", $device['os'], 1); 136 137 if ($config['os'][$device['os']]['group']) 138 { 139 $device['os_group'] = $config['os'][$device['os']]['group']; 140 print_cli_data("OS Group", $device['os_group'], 1); 141 } 142 143 if (is_numeric($device['last_polled_timetaken'])) 144 { 145 print_cli_data("Last poll duration", $device['last_polled_timetaken']. " seconds", 1); 146 } 147 148 print_cli_data("Last Polled", $device['last_polled'], 1); 149 print_cli_data("SNMP Version", $device['snmp_version'], 1); 150 151 //unset($poll_update); unset($poll_update_query); unset($poll_separator); 152 $update_array = array(); 153 154 $host_rrd_dir = $config['rrd_dir'] . "/" . $device['hostname']; 155 if (!is_dir($host_rrd_dir)) { mkdir($host_rrd_dir); echo("Created directory : $host_rrd_dir\n"); } 156 157 $flags = OBS_DNS_ALL; 158 if ($device['snmp_transport'] == 'udp6' || $device['snmp_transport'] == 'tcp6') // Exclude IPv4 if used transport 'udp6' or 'tcp6' 159 { 160 $flags = $flags ^ OBS_DNS_A; 161 } 162 $attribs['ping_skip'] = isset($attribs['ping_skip']) && $attribs['ping_skip']; 163 if ($attribs['ping_skip']) 164 { 165 $flags = $flags | OBS_PING_SKIP; // Add skip ping flag 166 } 167 $device['pingable'] = isPingable($device['hostname'], $flags); 168 if ($device['pingable']) 169 { 170 $device['snmpable'] = isSNMPable($device); 171 if ($device['snmpable']) 172 { 173 $ping_msg = ($attribs['ping_skip'] ? '' : 'PING (' . $device['pingable'] . 'ms) and '); 174 175 print_cli_data("Device status", "Device is reachable by " . $ping_msg . "SNMP (".$device['snmpable']."ms)", 1); 176 $status = "1"; 177 $status_type = 'ok'; 178 } else { 179 print_cli_data("Device status", "Device is not responding to SNMP requests", 1); 180 $status = "0"; 181 $status_type = 'snmp'; 182 } 183 } else { 184 print_cli_data("Device status", "Device is not responding to PINGs", 1); 185 $status = "0"; 186 print_vars(get_status_var('ping_dns')); 187 if (isset_status_var('ping_dns') && get_status_var('ping_dns') != 'ok') 188 { 189 $status_type = 'dns'; 190 } else { 191 $status_type = 'ping'; 192 } 193 } 194 195 196 if ($device['status'] != $status) 197 { 198 dbUpdate(array('status' => $status), 'devices', 'device_id = ?', array($device['device_id'])); 199 // dbInsert(array('importance' => '0', 'device_id' => $device['device_id'], 'message' => "Device is " .($status == '1' ? 'up' : 'down')), 'alerts'); 200 201 $event_msg = 'Device status changed to '; 202 if ($status == '1') 203 { 204 // Device Up, Severity Warning (4) 205 $event_msg .= 'Up'; 206 $event_severity = 4; 207 } else { 208 // Device Down, Severity Error (3)! 209 $event_msg .= 'Down'; 210 $event_severity = 3; 211 } 212 if ($status_type != 'ok') { $event_msg .= ' (' . $status_type . ')'; } 213 log_event($event_msg, $device, 'device', $device['device_id'], $event_severity); 214 } 215 // Device status type 216 if (isset($device['status_type']) && $device['status_type'] != $status_type) 217 { 218 dbUpdate(array('status_type' => $status_type), 'devices', 'device_id = ?', array($device['device_id'])); 219 if ($status == '0' && $device['status_type'] != 'ok') 220 { 221 // Write eventlog entry (only if status Down) 222 log_event('Device status changed to Down ('.$device['status_type'].' -> '.$status_type.')', $device, 'device', $device['device_id'], 3); 223 } 224 } 225 226 rrdtool_update_ng($device, 'status', array('status' => $status)); 227 228 if (!$attribs['ping_skip']) 229 { 230 // Ping response RRD database. 231 rrdtool_update_ng($device, 'ping', array('ping' => ($device['pingable'] ? $device['pingable'] : 'U'))); 232 } 233 234 // SNMP response RRD database. 235 rrdtool_update_ng($device, 'ping_snmp', array('ping_snmp' => ($device['snmpable'] ? $device['snmpable'] : 'U'))); 236 237 $alert_metrics['device_status'] = $status; 238 $alert_metrics['device_status_type'] = $status_type; 239 $alert_metrics['device_ping'] = $device['pingable']; // FIXME, when ping skipped, here always 0.001 240 $alert_metrics['device_snmp'] = $device['snmpable']; 241 242 if ($status == "1") 243 { 244 // Arrays for store and check enabled/disabled graphs 245 $graphs = array(); 246 $graphs_db = array(); 247 $graphs_insert = array(); 248 $graphs_delete = array(); 249 foreach (dbFetchRows("SELECT * FROM `device_graphs` WHERE `device_id` = ?", array($device['device_id'])) as $entry) 250 { 251 // Not know how empty was here 252 if (empty($entry['graph'])) 253 { 254 $graphs_delete[] = $entry['device_graph_id']; 255 } 256 257 $graphs_db[$entry['graph']] = $entry; 258 } 259 260 $graphs['availability'] = TRUE; // Everything has this! 261 262 if (!$attribs['ping_skip']) 263 { 264 // Enable Ping graphs 265 $graphs['ping'] = TRUE; 266 } 267 268 // Enable SNMP graphs 269 $graphs['ping_snmp'] = TRUE; 270 271 // Run these base modules always and before all other modules! 272 $poll_modules = array('system', 'os'); 273 274 if(isset($options['m']) && $options['m'] == 'none') 275 { 276 unset($poll_modules); 277 } 278 279 $mods_disabled_global = array(); 280 $mods_disabled_device = array(); 281 $mods_excluded = array(); 282 283 if ($options['m']) 284 { 285 foreach (explode(',', $options['m']) as $module) 286 { 287 $module = trim($module); 288 if (in_array($module, $poll_modules)) { continue; } // Skip already added modules 289 if ($module == 'unix-agent') 290 { 291 array_unshift($poll_modules, $module); // Add 'unix-agent' before all 292 continue; 293 } 294 if (is_file($config['install_dir'] . "/includes/polling/$module.inc.php")) 295 { 296 $poll_modules[] = $module; 297 } 298 } 299 } else { 300 foreach ($config['poller_modules'] as $module => $module_status) 301 { 302 if (in_array($module, $poll_modules)) { continue; } // Skip already added modules 303 if ($attribs['poll_'.$module] || ($module_status && !isset($attribs['poll_'.$module]))) 304 { 305 if (poller_module_excluded($device, $module)) 306 { 307 $mods_excluded[] = $module; 308 //print_warning("Module [ $module ] excluded for device."); 309 continue; 310 } 311 if ($module == 'unix-agent') 312 { 313 array_unshift($poll_modules, $module); // Add 'unix-agent' before all 314 continue; 315 } 316 if (is_file($config['install_dir'] . "/includes/polling/$module.inc.php")) 317 { 318 $poll_modules[] = $module; 319 } 320 } 321 elseif (isset($attribs['poll_'.$module]) && !$attribs['poll_'.$module]) 322 { 323 $mods_disabled_device[] = $module; 324 //print_warning("Module [ $module ] disabled on device."); 325 } else { 326 $mods_disabled_global[] = $module; 327 //print_warning("Module [ $module ] disabled globally."); 328 } 329 } 330 331 } 332 333 if (count($mods_excluded)) { print_cli_data("Modules Excluded", implode(", ", $mods_excluded), 1); } 334 if (count($mods_disabled_global)) { print_cli_data("Disabled Globally", implode(", ", $mods_disabled_global), 1); } 335 if (count($mods_disabled_device)) { print_cli_data("Disabled Device", implode(", ", $mods_disabled_global), 1); } 336 if (count($poll_modules)) { print_cli_data("Modules Enabled", implode(", ", $poll_modules), 1); } 337 338 echo(PHP_EOL); 339 340 foreach ($poll_modules as $module) 341 { 342 print_debug(PHP_EOL . "including: includes/polling/$module.inc.php"); 343 344 print_cli_heading("Module Start: %R".$module.""); 345 346 $m_start = utime(); 347 348 include($config['install_dir'] . "/includes/polling/$module.inc.php"); 349 350 $m_end = utime(); 351 352 $m_run = round($m_end - $m_start, 4); 353 $device_state['poller_mod_perf'][$module] = $m_run; 354 print_cli_data("Module time", number_format($m_run, 4)."s"); 355 356 if (!isset($options['m'])) 357 { 358 rrdtool_update_ng($device, 'perf-pollermodule', array('val' => $m_run), $module); 359 } 360 361 echo(PHP_EOL); 362 363 } 364 365 print_cli_heading($device['hostname']. " [" . $device['device_id'] . "] completed poller modules at " . date("Y-m-d H:i:s"), 1); 366 367 // Check and update graphs DB 368 $graphs_stat = array(); 369 370 if (!isset($options['m'])) 371 { 372 // Hardcoded poller performance 373 $graphs['poller_perf'] = TRUE; 374 $graphs['pollersnmp_count'] = TRUE; 375 $graphs['pollersnmp_times'] = TRUE; 376 $graphs['pollersnmp_errors_count'] = TRUE; 377 $graphs['pollersnmp_errors_times'] = TRUE; 378 $graphs['pollerdb_count'] = TRUE; 379 $graphs['pollerdb_times'] = TRUE; 380 $graphs['pollermemory_perf'] = TRUE; 381 382 // Delete not exists graphs from DB (only if poller run without modules option) 383 foreach ($graphs_db as $graph => $entry) 384 { 385 if (!isset($graphs[$graph])) 386 { 387 //dbDelete('device_graphs', "`device_id` = ? AND `graph` = ?", array($device['device_id'], $graph)); 388 $graphs_delete[] = $entry['device_graph_id']; 389 unset($graphs_db[$graph]); 390 $graphs_stat['deleted'][] = $graph; 391 } 392 } 393 } 394 395 // Add or update graphs in DB 396 foreach ($graphs as $graph => $value) 397 { 398 if (!$graph) { continue; } // Not know how here can empty 399 400 if (!isset($graphs_db[$graph])) 401 { 402 //dbInsert(array('device_id' => $device['device_id'], 'graph' => $graph, 'enabled' => $value), 'device_graphs'); 403 $graphs_insert[] = array('device_id' => $device['device_id'], 'graph' => $graph, 'enabled' => $value); 404 $graphs_stat['added'][] = $graph; 405 } 406 else if ($value != $graphs_db[$graph]['enabled']) 407 { 408 dbUpdate(array('enabled' => $value), 'device_graphs', '`device_graph_id` = ?', array($device['device_id'], $graph)); 409 $graphs_stat['updated'][] = $graph; 410 } else { 411 $graphs_stat['checked'][] = $graph; 412 } 413 } 414 if (count($graphs_insert)) 415 { 416 dbInsertMulti($graphs_insert, 'device_graphs'); 417 } 418 if (count($graphs_delete)) 419 { 420 dbDelete('device_graphs', generate_query_values($graphs_delete, 'device_graph_id', NULL, FALSE)); 421 } 422 423 // Print graphs stats 424 foreach ($graphs_stat as $key => $stat) 425 { 426 if (count($stat)) { print_cli_data('Graphs ['.$key.']', implode(', ', $stat), 1); } 427 } 428 429 $device_end = utime(); 430 $device_run = $device_end - $device_start; 431 $device_time = round($device_run, 4); 432 433 $update_array['last_polled'] = array('NOW()'); 434 $update_array['last_polled_timetaken'] = $device_time; 435 436 #echo("$device_end - $device_start; $device_time $device_run"); 437 438 print_cli_data("Poller time", $device_time." seconds", 1); 439 //print_message(PHP_EOL."Polled in $device_time seconds"); 440 441 // Store device stats and history data (only) if we're not doing a single-module poll 442 if (!$options['m']) 443 { 444 445 // Fetch previous device state (do not use $device array here, for exclude update history collisions) 446 $old_device_state = dbFetchCell('SELECT `device_state` FROM `devices` WHERE `device_id` = ?;', array($device['device_id'])); 447 $old_device_state = unserialize($old_device_state); 448 449 // Add first entry 450 $poller_history = array(intval($device_start) => $device_time); // start => duration 451 // Add and keep not more than 288 (24 hours with 5min interval) last entries 452 if (isset($old_device_state['poller_history'])) 453 { 454 print_debug_vars($old_device_state['poller_history']); 455 $poller_history = array_slice($poller_history + $old_device_state['poller_history'], 0, 288, TRUE); 456 } 457 print_debug_vars($poller_history); 458 459 $device_state['poller_history'] = $poller_history; 460 461 // Keep discovery history and perf too 462 if (isset($old_device_state['discovery_history'])) 463 { 464 $device_state['discovery_history'] = $old_device_state['discovery_history']; 465 } 466 if (isset($old_device_state['discovery_mod_perf'])) 467 { 468 $device_state['discovery_mod_perf'] = $old_device_state['discovery_mod_perf']; 469 } 470 unset($poller_history, $old_device_state); 471 472 $update_array['device_state'] = serialize($device_state); 473 474 // Also store history in graph 475 rrdtool_update_ng($device, 'perf-poller', array('val' => $device_time)); 476 } 477 478 if (OBS_DEBUG) 479 { 480 echo("Updating " . $device['hostname'] . " - "); 481 print_vars($update_array); 482 echo(" \n"); 483 } 484 485 $updated = dbUpdate($update_array, 'devices', '`device_id` = ?', array($device['device_id'])); 486 487 if ($updated) { 488 print_cli_data("Updated Data", implode(", ", array_keys($update_array)), 1); 489 } 490 491 $alert_metrics['device_la'] = $device_state['la']['5min']; // 5 min as common LA 492 $alert_metrics['device_la_1min'] = $device_state['la']['1min']; 493 $alert_metrics['device_la_5min'] = $device_state['la']['5min']; 494 $alert_metrics['device_la_15min'] = $device_state['la']['15min']; 495 496 $alert_metrics['device_uptime'] = $device['uptime']; 497 $alert_metrics['device_rebooted'] = $rebooted; // 0 - not rebooted, 1 - rebooted 498 $alert_metrics['device_duration_poll'] = $device['last_polled_timetaken']; 499 500 unset($cache_storage); // Clear cache of hrStorage ** MAYBE FIXME? ** (ok, later) 501 unset($cache); // Clear cache (unify all things here?) 502 503 } else if (!$options['m']) { 504 // State is 0, also collect poller time for down devices, since it not zero! 505 506 $device_end = utime(); 507 $device_run = $device_end - $device_start; 508 $device_time = round($device_run, 4); 509 510 print_cli_data("Poller time", $device_time." seconds", 1); 511 // Also store history in graph 512 rrdtool_update_ng($device, 'perf-poller', array('val' => $device_time)); 513 } 514 515 check_entity('device', $device, $alert_metrics); 516 517 echo(PHP_EOL); 518 519 // Clean 520 del_process_info($device); // Remove process info 521 unset($alert_metrics); 522} 523 524///FIXME. It's not a very nice solution, but will approach as temporal. 525// Function return FALSE, if poller module allowed for device os (otherwise TRUE). 526function poller_module_excluded($device, $module) 527{ 528 global $config; 529 530 ///FIXME. rename module: 'wmi' -> 'windows-wmi' 531 if ($module == 'wmi' && $device['os'] != 'windows') { return TRUE; } 532 533 if ($module == 'ipmi' && 534 (!isset($config['os'][$device['os']]['ipmi']) || $config['os'][$device['os']]['ipmi'] == FALSE)) { return TRUE; } 535 if ($module == 'unix-agent' && !($device['os_group'] == 'unix' || $device['os'] == 'generic')) { return TRUE; } 536 537 if (isset($config['os'][$device['os']]['poller_blacklist'])) 538 { 539 if (in_array($module, $config['os'][$device['os']]['poller_blacklist'])) 540 { 541 return TRUE; 542 } 543 } 544 545 $os_test = explode('-', $module, 2); 546 if (count($os_test) === 1) { return FALSE; } // Check modules only with a dash. 547 list($os_test) = $os_test; 548 549 ///FIXME. rename module: 'cipsec-tunnels' -> 'cisco-ipsec-tunnels' 550 if (($os_test == 'cisco' || $os_test == 'cipsec') && $device['os_group'] != 'cisco') { return TRUE; } 551 //$os_groups = array('cisco', 'unix'); 552 //foreach ($os_groups as $os_group) 553 //{ 554 // if ($os_test == $os_group && $device['os_group'] != $os_group) { return TRUE; } 555 //} 556 557 $oses = array('junose', 'arista_eos', 'netscaler', 'arubaos'); 558 foreach ($oses as $os) 559 { 560 if (strpos($os, $os_test) !== FALSE && $device['os'] != $os) { return TRUE; } 561 } 562 563 return FALSE; 564} 565 566/** 567 * Poll a table or oids from SNMP and build an RRD based on an array of arguments. 568 * 569 * Current limitations: 570 * - single MIB and RRD file for all graphs 571 * - single table per MIB 572 * - if set definition 'call_function', than poll used specific function for snmp walk/get, 573 * else by default used snmpwalk_cache_oid() 574 * - allowed oids only with simple numeric index (oid.0, oid.33), NOT allowed (oid.1.2.23) 575 * - only numeric data 576 * 577 * Example of (full) args array: 578 * array( 579 * 'file' => 'someTable.rrd', // [MANDATORY] RRD filename, but if not set used MIB_table.rrd as filename 580 * 'call_function' => 'snmpwalk_cache_oid' // [OPTIONAL] Which function to use for snmp poll, bu default snmpwalk_cache_oid() 581 * 'mib' => 'SOMETHING-MIB', // [OPTIONAL] MIB or list of MIBs separated by a colon 582 * 'mib_dir' => 'something', // [OPTIONAL] OS MIB directory or array of directories 583 * 'graphs' => array('one','two'), // [OPTIONAL] List of graph_types that this table provides 584 * 'table' => 'someTable', // [RECOMENDED] Table name for OIDs 585 * 'numeric' => '.1.3.6.1.4.1.555.4.1.1.48', // [OPTIONAL] Numeric table OID 586 * 'index' => '1', // [OPTIONAL] Force an OID index for the entire table. If not set, equals '0' 587 * 'ds_rename' => array('http' => ''), // [OPTIONAL] Array for renaming OIDs to DSes 588 * 'oids' => array( // List of OIDs you can use as key: full OID name 589 * 'someOid' => array( // OID name (You can use OID name, like 'cpvIKECurrSAs') 590 * 'descr' => 'Current IKE SAs', // [OPTIONAL] Description of the OID contents 591 * 'numeric' => '.1.3.6.1.4.1.555.4.1.1.48.45', // [OPTIONAL] Numeric OID 592 * 'index' => '0', // [OPTIONAL] OID index, if not set equals '0' 593 * 'ds_name' => 'IKECurrSAs', // [OPTIONAL] DS name, if not set used OID name truncated to 19 chars 594 * 'ds_type' => 'GAUGE', // [OPTIONAL] DS type, if not set equals 'COUNTER' 595 * 'ds_min' => '0', // [OPTIONAL] Min value for DS, if not set equals 'U' 596 * 'ds_max' => '30000' // [OPTIONAL] Max value for DS, if not set equals '100000000000' 597 * ) 598 * ) 599 * 600 */ 601function collect_table($device, $oids_def, &$graphs) 602{ 603 $rrd = array(); 604 $mib = NULL; 605 $mib_dirs = NULL; 606 $use_walk = isset($oids_def['table']) && $oids_def['table']; // Use snmpwalk by default 607 $call_function = strtolower($oids_def['call_function']); 608 switch ($call_function) 609 { 610 case 'snmp_get': 611 case 'snmp_get_multi': 612 $use_walk = FALSE; 613 break; 614 case 'snmpwalk_cache_bare_oid': 615 break; 616 case 'snmpwalk_cache_oid': 617 default: 618 $call_function = 'snmpwalk_cache_oid'; 619 if (!$use_walk) 620 { 621 // Break because we should use snmpwalk, but walking table not set 622 return FALSE; 623 } 624 } 625 if (isset($oids_def['numeric'])) { $oids_def['numeric'] = '.'.trim($oids_def['numeric'], '. '); } // Remove trailing dot 626 if (isset($oids_def['mib'])) { $mib = $oids_def['mib']; } 627 if (isset($oids_def['mib_dir'])) { $mib_dirs = mib_dirs($oids_def['mib_dir']); } 628 if (isset($oids_def['file'])) 629 { 630 $rrd_file = $oids_def['file']; 631 } 632 elseif ($mib && isset($oids_def['table'])) 633 { 634 // Try to use MIB & tableName as rrd_file 635 $rrd_file = strtolower(safename($mib.'_'.$oids_def['table'])).'.rrd'; 636 } else { 637 print_debug(" WARNING, not have rrd filename."); 638 return FALSE; // Not have RRD filename 639 } 640 641 // Get MIBS/Tables/OIDs permissions 642 if ($use_walk) 643 { 644 // if use table walk, than check only this table disabled (not oids) 645 $disabled_tables = get_device_objects_disabled($device, $mib); 646 if (in_array($oids_def['table'], $disabled_tables)) 647 { 648 print_debug(" WARNING, table '".$oids_def['table']."' for '$mib' disabled and skipped."); 649 return FALSE; // table disabled, exit 650 } 651 } else { 652 // if use multi_get, than check all oids disabled 653 $disabled_oids = get_device_objects_disabled($device, $mib); 654 $oids_ok = array_diff(array_keys($oids_def['oids']), $disabled_oids); 655 if (count($oids_ok) == 0) 656 { 657 print_debug(" WARNING, oids '".implode("', '", array_keys($oids_def['oids']))."' for '$mib' disabled and skipped."); 658 return FALSE; // All oids disabled, exit 659 } 660 } 661 662 $search = array(); 663 $replace = array(); 664 if (is_array($oids_def['ds_rename'])) 665 { 666 foreach ($oids_def['ds_rename'] as $s => $r) 667 { 668 $search[] = $s; 669 $replace[] = $r; 670 } 671 } 672 673 // rrd DS limit is 20 bytes (19 chars + NULL terminator) 674 $ds_len = 19; 675 676 $oids = array(); 677 $oids_index = array(); 678 foreach ($oids_def['oids'] as $oid => $entry) 679 { 680 if (is_numeric($entry['numeric']) && isset($oids_def['numeric'])) 681 { 682 $entry['numeric'] = $oids_def['numeric'] . '.' . $entry['numeric']; // Numeric oid, for future using 683 } 684 if (!isset($entry['index']) && isset($oids_def['index'])) 685 { 686 $entry['index'] = $oids_def['index']; 687 } 688 elseif (!isset($entry['index'])) 689 { 690 $entry['index'] = '0'; 691 } 692 if (!isset($entry['ds_type'])) { $entry['ds_type'] = 'COUNTER'; } 693 if (!isset($entry['ds_min'])) { $entry['ds_min'] = 'U'; } 694 if (!isset($entry['ds_max'])) { $entry['ds_max'] = '100000000000'; } 695 if (!isset($entry['ds_name'])) 696 { 697 // Convert OID name to DS name 698 $ds_name = $oid; 699 if (is_array($oids_def['ds_rename'])) { $ds_name = str_replace($search, $replace, $ds_name); } 700 } else { 701 $ds_name = $entry['ds_name']; 702 } 703 if (strlen($ds_name) > $ds_len) { $ds_name = truncate($ds_name, $ds_len, ''); } 704 705 if (isset($oids_def['no_index']) && $oids_def['no_index'] == TRUE) 706 { 707 $oids[] = $oid; 708 } else { 709 $oids[] = $oid.'.'.$entry['index']; 710 } 711 $oids_index[] = array('index' => $entry['index'], 'oid' => $oid); 712 713 $rrd['rrd_create'][] = ' DS:'.$ds_name.':'.$entry['ds_type'].':600:'.$entry['ds_min'].':'.$entry['ds_max']; 714 if (OBS_DEBUG) { $rrd['ds_list'][] = $ds_name; } // Make DS lists for compare with RRD file in debug 715 } 716 717 switch ($call_function) 718 { 719 case 'snmpwalk_cache_oid': 720 $data = snmpwalk_cache_oid($device, $oids_def['table'], array(), $mib, $mib_dirs); 721 break; 722 case 'snmpwalk_cache_bare_oid': 723 $data = snmpwalk_cache_bare_oid($device, $oids_def['table'], array(), $mib, $mib_dirs); 724 break; 725 case 'snmp_get': 726 case 'snmp_get_multi': 727 case 'snmp_get_multi_oid': 728 $data = snmp_get_multi_oid($device, $oids, array(), $mib, $mib_dirs); 729 break; 730 } 731 if (!snmp_status()) 732 { 733 // Break because latest snmp walk/get return not good exitstatus (wrong mib/timeout/error/etc) 734 print_debug(" WARNING, latest snmp walk/get return not good exitstatus for '$mib', RRD update skipped."); 735 return FALSE; 736 } 737 738 //print_debug_vars($data); 739 740 if (isset($oids_def['no_index']) && $oids_def['no_index'] == TRUE || $call_function == 'snmpwalk_cache_double_oid') 741 { 742 $data[0] = $data['']; 743 } 744 elseif ( $call_function == 'snmpwalk_cache_bare_oid') 745 { 746 $data[0] = $data; 747 } 748 749 print_debug_vars($data); 750 751 foreach ($oids_index as $entry) 752 { 753 $index = $entry['index']; 754 $oid = $entry['oid']; 755 756 if (is_numeric($data[$index][$oid])) 757 { 758 // The original OID definition from the table. 759 $def = $oids_def['oids'][$oid]; 760 761 // Apply multiplier value from the entry 762 if (isset($def['multiplier']) && $def['multiplier'] != 0) 763 { 764 $data[$index][$oid] = scale_value($data[$index][$oid], $def['multiplier']); 765 } 766 767 $rrd['ok'] = TRUE; // We have any data for current rrd_file 768 $rrd['rrd_update'][] = $data[$index][$oid]; 769 } else { 770 $rrd['rrd_update'][] = 'U'; 771 } 772 } 773 774 // Ok, all previous checks done, update RRD, table/oids permissions, $graphs 775 if (isset($rrd['ok']) && $rrd['ok']) 776 { 777 // Create/update RRD file 778 $rrd_create = implode('', $rrd['rrd_create']); 779 $rrd_update = 'N:'.implode(':', $rrd['rrd_update']); 780 rrdtool_create($device, $rrd_file, $rrd_create); 781 rrdtool_update($device, $rrd_file, $rrd_update); 782 783 foreach ($oids_def['graphs'] as $graph) 784 { 785 $graphs[$graph] = TRUE; // Set all graphs to TRUE 786 } 787 788 // Compare DSes form RRD file with DSes from array 789 if (OBS_DEBUG) 790 { 791 $graph_template = "\$config['graph_types']['device']['GRAPH_CHANGE_ME'] = array(\n"; 792 $graph_template .= " 'file' => '$rrd_file',\n"; 793 $graph_template .= " 'ds' => array(\n"; 794 $rrd_file_info = rrdtool_file_info(get_rrd_path($device, $rrd_file)); 795 foreach ($rrd_file_info['DS'] as $ds => $nothing) 796 { 797 $ds_list[] = $ds; 798 $graph_template .= " '$ds' => array('label' => '$ds'),\n"; 799 } 800 $graph_template .= " )\n);"; 801 $in_args = array_diff($rrd['ds_list'], $ds_list); 802 if ($in_args) 803 { 804 print_message("%rWARNING%n, in file '%W".$rrd_file_info['filename']."%n' different DS lists. NOT have: ".implode(', ', $in_args)); 805 } 806 $in_file = array_diff($ds_list, $rrd['ds_list']); 807 if ($in_file) 808 { 809 print_message("%rWARNING%n, in file '%W".$rrd_file_info['filename']."%n' different DS lists. Excess: ".implode(', ', $in_file)); 810 } 811 812 // Print example for graph template using rrd_file and ds list 813 print_message($graph_template); 814 } 815 } 816 else if ($use_walk) 817 { 818 // Table NOT exist on device! 819 // Disable polling table (only if table not enabled manually in DB) 820 821 // This code just disables collection forever after the first failed query! 822 823 /* 824 if (!dbFetchCell("SELECT COUNT(*) FROM `devices_mibs` WHERE `device_id` = ? AND `mib` = ? 825 AND `table_name` = ? AND (`oid` = '' OR `oid` IS NULL)", array($device['device_id'], $mib, $oids_def['table']))) 826 { 827 dbInsert(array('device_id' => $device['device_id'], 'mib' => $mib, 828 'table_name' => $oids_def['table'], 'disabled' => '1'), 'devices_mibs'); 829 } 830 print_debug(" WARNING, table '".$oids_def['table']."' for '$mib' disabled."); 831 */ 832 } else { 833 // OIDs NOT exist on device! 834 // Disable polling oids (only if table not enabled manually in DB) 835 /* 836 foreach (array_keys($oids_def['oids']) as $oid) 837 { 838 if (!dbFetchCell("SELECT COUNT(*) FROM `devices_mibs` WHERE `device_id` = ? AND `mib` = ? 839 AND `oid` = ?", array($device['device_id'], $mib, $oid))) 840 { 841 dbInsert(array('device_id' => $device['device_id'], 'mib' => $mib, 842 'oid' => $oid, 'disabled' => '1'), 'devices_mibs'); 843 } 844 } 845 print_debug(" WARNING, oids '".implode("', '", array_keys($oids_def['oids']))."' for '$mib' disabled."); 846 */ 847 } 848 849 // Return obtained snmp data 850 return $data; 851} 852 853function poll_p2p_radio($device, $mib, $index, $radio) 854{ 855 $params = array('radio_tx_freq', 'radio_rx_freq', 'radio_tx_power', 'radio_rx_level', 'radio_name', 'radio_bandwidth', 'radio_modulation', 'radio_total_capacity', 'radio_standard', 'radio_loopback', 'radio_tx_mute', 'radio_eth_capacity', 'radio_e1t1_channels', 'radio_cur_capacity'); 856 857 if (is_array($GLOBALS['cache']['p2p_radios'][$mib][$index])) { $radio_db = $GLOBALS['cache']['p2p_radios'][$mib][$index]; } 858 859 // Update the Database 860 861 if (!isset($radio_db['radio_id'])) // If we don't have an entry already, create it 862 { 863 $insert = array(); 864 $insert['device_id'] = $device['device_id']; 865 $insert['radio_mib'] = $mib; 866 $insert['radio_index'] = $index; 867 868 foreach ($params as $param) 869 { 870 $insert[$param] = $radio[$param]; 871 if ($radio[$param] == NULL) { $insert[$param] = array('NULL'); } 872 } 873 874 $radio_id = dbInsert($insert, 'p2p_radios'); 875 echo("+"); 876 877 } else { // If we already have an entry, check if it needs updating 878 879 $update = array(); 880 foreach ($params as $param) 881 { 882 if ($radio[$param] != $radio_db[$param]) { $update[$param] = $radio[$param]; } 883 } 884 if (count($update)) // If there have been changes, update it 885 { 886 dbUpdate($update, 'p2p_radios', '`radio_id` = ?', array($radio_db['radio_id'])); 887 echo('U'); 888 } else { 889 echo('.'); 890 } 891 } 892 893 rrdtool_update_ng($device, 'p2p_radio', array( 894 'tx_power' => $radio['radio_tx_power'], 895 'rx_level' => $radio['radio_rx_level'], 896 'rmse' => $radio['radio_rmse'], 897 'agc_gain' => $radio['radio_agc_gain'], 898 'cur_capacity' => $radio['radio_cur_capacity'], 899 'sym_rate_tx' => $radio['radio_sym_rate_tx'], 900 'sym_rate_rx' => $radio['radio_sym_rate_tx'], 901 ), "$mib-$index"); 902 903 $GLOBALS['valid']['p2p_radio'][$mib][$index] = 1; // FIXME. What? How it passed there? 904} 905 906function update_application($app_id, $app_data) 907{ 908 909 $update_array = array('app_json' => json_encode($app_data), 'app_lastpolled' => time()); 910 911 dbUpdate($update_array, 'applications', '`app_id` = ?', array($app_id)); 912 913} 914 915// EOF 916