예제 #1
0
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);
}
예제 #2
0
<?php

/**
 * Observium Network Management and Monitoring System
 * Copyright (C) 2006-2015, Adam Armstrong - http://www.observium.org
 *
 * @package    observium
 * @subpackage webui
 * @author     Adam Armstrong <*****@*****.**>
 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2016 Observium Limited
 *
 */
$alert_rules = cache_alert_rules();
$alert_assoc = cache_alert_assoc();
$alert_table = cache_device_alert_table($device['device_id']);
$vars['pagination'] = TRUE;
print_alert_table(array('entity_type' => 'port', 'entity_id' => $port['port_id']));
// EOF
예제 #3
0
/**
 * Display events.
 *
 * Display pages with alert logs in multiple formats.
 * Examples:
 * print_alert_log() - display last 10 events from all devices
 * print_alert_log(array('pagesize' => 99)) - display last 99 events from all device
 * print_alert_log(array('pagesize' => 10, 'pageno' => 3, 'pagination' => TRUE)) - display 10 events from page 3 with pagination header
 * print_alert_log(array('pagesize' => 10, 'device' = 4)) - display last 10 events for device_id 4
 * print_alert_log(array('short' => TRUE)) - show small block with last events
 *
 * @param array $vars
 * @return none
 *
 */
function print_alert_log($vars)
{
    global $alert_rules, $config;
    // This should be set outside, but do it here if it isn't
    if (!is_array($alert_rules)) {
        $alert_rules = cache_alert_rules();
    }
    // Get events array
    $events = get_alert_log($vars);
    if (!$events['count']) {
        if (!$vars['no_empty_message']) {
            // There have been no entries returned. Print the warning.
            print_message('<h4>No alert log entries found!</h4>', FALSE);
        }
    } else {
        // Entries have been returned. Print the table.
        $list = array('device' => FALSE, 'entity' => FALSE);
        if (!isset($vars['device']) || empty($vars['device']) || $vars['page'] == 'alert_log') {
            $list['device'] = TRUE;
        }
        if ($events['short'] || !isset($vars['entity']) || empty($vars['entity'])) {
            $list['entity'] = TRUE;
        }
        if (!isset($vars['alert_test_id']) || empty($vars['alert_test_id']) || $vars['page'] == 'alert_check' || TRUE) {
            $list['alert_test_id'] = TRUE;
        }
        if (!isset($vars['entity_type']) || empty($vars['entity_type']) || $vars['page'] == 'alert_check' || TRUE) {
            $list['entity_type'] = TRUE;
        }
        $string = generate_box_open($vars['header']);
        $string .= '<table class="table table-striped table-hover table-condensed-more">' . PHP_EOL;
        if (!$events['short']) {
            $cols = array();
            $cols[] = array(NULL, 'class="state-marker"');
            $cols['date'] = array('Date', 'style="width: 160px"');
            if ($list['device']) {
                $cols['device'] = 'Device';
            }
            if ($list['alert_test_id']) {
                $cols['alert_test_id'] = 'Alert Check';
            }
            if ($list['entity']) {
                $cols['entity'] = 'Entity';
            }
            $cols[] = 'Message';
            $cols['status'] = 'Status';
            $cols['notified'] = array('Notified', 'style="width: 40px"');
            $string .= get_table_header($cols);
            // , $vars); // Actually sorting is disabled now
        }
        $string .= '  <tbody>' . PHP_EOL;
        foreach ($events['entries'] as $entry) {
            $alert_rule = $alert_rules[$entry['alert_test_id']];
            // Functionize?
            // Set colours and classes based on the status of the alert
            if ($entry['log_type'] == 'OK') {
                $entry['class'] = "green";
                $entry['html_row_class'] = "success";
            } else {
                if ($entry['log_type'] == 'RECOVER_NOTIFY') {
                    $entry['class'] = "green";
                    $entry['html_row_class'] = "info";
                } else {
                    if ($entry['log_type'] == 'ALERT_NOTIFY') {
                        $entry['class'] = "red";
                        $entry['html_row_class'] = "error";
                    } elseif ($entry['log_type'] == 'FAIL') {
                        $entry['class'] = "red";
                        $entry['html_row_class'] = "error";
                    } elseif ($entry['log_type'] == 'FAIL_DELAYED') {
                        $entry['class'] = "purple";
                        $entry['html_row_class'] = "warning";
                    } elseif ($entry['log_type'] == 'FAIL_SUPPRESSED') {
                        $entry['class'] = "purple";
                        $entry['html_row_class'] = "suppressed";
                    } elseif ($entry['log_type'] == 'RECOVER_SUPPRESSED') {
                        $entry['class'] = "purple";
                        $entry['html_row_class'] = "suppressed";
                    } else {
                        // Anything else set the colour to grey and the class to disabled.
                        $entry['class'] = "gray";
                        $entry['html_row_class'] = "disabled";
                    }
                }
            }
            $string .= '  <tr class="' . $entry['html_row_class'] . '">' . PHP_EOL;
            $string .= '<td class="state-marker"></td>' . PHP_EOL;
            if ($events['short']) {
                $string .= '    <td class="syslog" style="white-space: nowrap">';
                $timediff = $GLOBALS['config']['time']['now'] - strtotime($entry['timestamp']);
                $string .= generate_tooltip_link('', formatUptime($timediff, "short-3"), format_timestamp($entry['timestamp']), NULL) . '</td>' . PHP_EOL;
            } else {
                $string .= '    <td>';
                $string .= format_timestamp($entry['timestamp']) . '</td>' . PHP_EOL;
            }
            if ($list['device']) {
                $dev = device_by_id_cache($entry['device_id']);
                $device_vars = array('page' => 'device', 'device' => $entry['device_id'], 'tab' => 'logs', 'section' => 'alertlog');
                $string .= '    <td class="entity">' . generate_device_link($dev, short_hostname($dev['hostname']), $device_vars) . '</td>' . PHP_EOL;
            }
            if ($list['alert_test_id']) {
                $string .= '     <td class="entity"><a href="' . generate_url(array('page' => 'alert_check', 'alert_test_id' => $alert_rule['alert_test_id'])) . '">' . escape_html($alert_rule['alert_name']) . '</a></td>';
            }
            if ($list['entity']) {
                $string .= '    <td class="entity">';
                if ($list['entity_type']) {
                    $string .= '<i class="' . $config['entities'][$entry['entity_type']]['icon'] . '"></i> ';
                }
                if ($events['short']) {
                    $string .= '    ' . generate_entity_link($entry['entity_type'], $entry['entity_id'], NULL, NULL, NULL, TRUE) . '</td>' . PHP_EOL;
                } else {
                    $string .= '    ' . generate_entity_link($entry['entity_type'], $entry['entity_id']) . '</td>' . PHP_EOL;
                }
            }
            $string .= '<td>' . escape_html($entry['message']) . '</td>' . PHP_EOL;
            if (!$vars['short']) {
                $string .= '<td>' . escape_html($entry['log_type']) . '</td>' . PHP_EOL;
                $string .= '<td style="text-align: right">' . ($entry['notified'] ? '<span class="label label-success">YES</span>' : '<span class="label">NO</span>') . '</td>' . PHP_EOL;
            }
            $string .= '  </tr>' . PHP_EOL;
        }
        $string .= '  </tbody>' . PHP_EOL;
        $string .= '</table>';
        $string .= generate_box_close();
        // Print pagination header
        if ($events['pagination_html']) {
            $string = $events['pagination_html'] . $string . $events['pagination_html'];
        }
        // Print events
        echo $string;
    }
}
예제 #4
0
/**
 * Display alert_table entries.
 *
 * @param array $vars
 * @return none
 *
 */
function print_alert_table($vars)
{
    global $alert_rules;
    global $config;
    // This should be set outside, but do it here if it isn't
    if (!is_array($alert_rules)) {
        $alert_rules = cache_alert_rules();
    }
    /// WARN HERE
    if (isset($vars['device']) && !isset($vars['device_id'])) {
        $vars['device_id'] = $vars['device'];
    }
    if (isset($vars['entity']) && !isset($vars['entity_id'])) {
        $vars['entity_id'] = $vars['entity'];
    }
    // Short? (no pagination, small out)
    $short = isset($vars['short']) && $vars['short'];
    list($query, $param, $query_count) = build_alert_table_query($vars);
    // Fetch alerts
    $count = dbFetchCell($query_count, $param);
    $alerts = dbFetchRows($query, $param);
    // Set which columns we're going to show.
    // We hide the columns that have been given as search options via $vars
    $list = array('device_id' => FALSE, 'entity_id' => FALSE, 'entity_type' => FALSE, 'alert_test_id' => FALSE);
    foreach ($list as $argument => $nope) {
        if (!isset($vars[$argument]) || empty($vars[$argument]) || $vars[$argument] == "all") {
            $list[$argument] = TRUE;
        }
    }
    // Hide device if we know entity_id
    if (isset($vars['entity_id'])) {
        $list['device_id'] = FALSE;
    }
    // Hide entity_type if we know the alert_test_id
    if (isset($vars['alert_test_id']) || TRUE) {
        $list['entity_type'] = FALSE;
    }
    // Hide entity types in favour of icons to save space
    if ($vars['pagination'] && !$short) {
        $pagination_html = pagination($vars, $count);
        echo $pagination_html;
    }
    echo '<table class="table table-condensed table-bordered table-striped table-rounded table-hover">
  <thead>
    <tr>
      <th class="state-marker"></th>
      <th style="width: 1px;"></th>';
    // No table id
    //<th style="width: 5%;">Id</th>');
    if ($list['device_id']) {
        echo '      <th style="width: 15%">设备</th>';
    }
    if ($list['alert_test_id']) {
        echo '      <th style="min-width: 15%;">警报</th>';
    }
    if ($list['entity_type']) {
        echo '      <th style="width: 10%">类型</th>';
    }
    if ($list['entity_id']) {
        echo '      <th style="">实体</th>';
    }
    echo '
      <th style="width: 20px">状态</th>
      <th style="width: 100px;">信息</th>
      <th style="width: 90px;">已检测</th>
      <th style="width: 90px;">已更改</th>
      <th style="width: 90px;">警告</th>
      <th style="width: 20px;"></th>
    </tr>
  </thead>
  <tbody>' . PHP_EOL;
    foreach ($alerts as $alert) {
        // Process the alert entry, generating colours and classes from the data
        humanize_alert_entry($alert);
        // Get the entity array using the cache
        $entity = get_entity_by_id_cache($alert['entity_type'], $alert['entity_id']);
        // Get the device array using the cache
        $device = device_by_id_cache($alert['device_id']);
        // Get the entity_name.
        ### FIXME - This is probably duplicated effort from above. We should pass it $entity
        $entity_name = entity_name($alert['entity_type'], $entity);
        // Set the alert_rule from the prebuilt cache array
        $alert_rule = $alert_rules[$alert['alert_test_id']];
        echo '<tr class="' . $alert['html_row_class'] . '" style="cursor: pointer;" onclick="location.href=\'' . generate_url(array('page' => 'device', 'device' => $device['device_id'], 'tab' => 'alert', 'alert_entry' => $alert['alert_table_id'])) . '\'">';
        echo '<td class="state-marker"></td>';
        echo '<td style="width: 1px;"></td>';
        // If we know the device, don't show the device
        if ($list['device_id']) {
            echo '<td><span class="entity-title">' . generate_device_link($device) . '</span></td>';
        }
        // Print link to the alert rule page
        if ($list['alert_test_id']) {
            echo '<td><a href="', generate_url(array('page' => 'alert_check', 'alert_test_id' => $alert_rule['alert_test_id'])), '">', $alert_rule['alert_name'], '</a></td>';
        }
        // If we're showing all entity types, print the entity type here
        if ($list['entity_type']) {
            echo '<td>' . nicecase($alert['entity_type']) . '</td>';
        }
        // Print a link to the entity
        if ($list['entity_id']) {
            echo '<td><span class="entity-title"><i class="' . $config['entities'][$alert['entity_type']]['icon'] . '"></i> ' . generate_entity_link($alert['entity_type'], $alert['entity_id']) . '</span></td>';
        }
        echo '<td>';
        ## FIXME -- generate a nice popup with parsed information from the state array
        echo overlib_link("", '<i class="icon-info-sign"></i>', "<pre>" . print_r(json_decode($alert['state'], TRUE), TRUE) . "</pre>", NULL);
        echo '</td>';
        echo '<td class="' . $alert['class'] . '">' . $alert['last_message'] . '</td>';
        echo '<td>' . overlib_link('', $alert['checked'], format_unixtime($alert['last_checked'], 'r'), NULL) . '</td>';
        echo '<td>' . overlib_link('', $alert['changed'], format_unixtime($alert['last_changed'], 'r'), NULL) . '</td>';
        echo '<td>' . overlib_link('', $alert['alerted'], format_unixtime($alert['last_alerted'], 'r'), NULL) . '</td>';
        echo '<td><a href="' . generate_url(array('page' => 'device', 'device' => $device['device_id'], 'tab' => 'alert', 'alert_entry' => $alert['alert_table_id'])) . '"><i class="oicon-gear" /></a></td>';
        echo '</tr>';
    }
    echo '  </tbody>' . PHP_EOL;
    echo '</table>' . PHP_EOL;
    if ($vars['pagination'] && !$short) {
        echo $pagination_html;
    }
}
예제 #5
0
/**
 * Display alert_table entries.
 *
 * @param array $vars
 * @return none
 *
 */
function print_alert_table($vars)
{
    global $alert_rules;
    global $config;
    // This should be set outside, but do it here if it isn't
    if (!is_array($alert_rules)) {
        $alert_rules = cache_alert_rules();
    }
    /// WARN HERE
    if (isset($vars['device']) && !isset($vars['device_id'])) {
        $vars['device_id'] = $vars['device'];
    }
    if (isset($vars['entity']) && !isset($vars['entity_id'])) {
        $vars['entity_id'] = $vars['entity'];
    }
    // Short? (no pagination, small out)
    $short = isset($vars['short']) && $vars['short'];
    list($query, $param, $query_count) = build_alert_table_query($vars);
    // Fetch alerts
    $count = dbFetchCell($query_count, $param);
    $alerts = dbFetchRows($query, $param);
    // Set which columns we're going to show.
    // We hide the columns that have been given as search options via $vars
    $list = array('device_id' => FALSE, 'entity_id' => FALSE, 'entity_type' => FALSE, 'alert_test_id' => FALSE);
    foreach ($list as $argument => $nope) {
        if (!isset($vars[$argument]) || empty($vars[$argument]) || $vars[$argument] == "all") {
            $list[$argument] = TRUE;
        }
    }
    if ($vars['format'] != "condensed") {
        $list['checked'] = TRUE;
        $list['changed'] = TRUE;
        $list['alerted'] = TRUE;
    }
    if ($vars['short'] == TRUE) {
        $list['checked'] = FALSE;
        $list['alerted'] = FALSE;
    }
    // Hide device if we know entity_id
    if (isset($vars['entity_id'])) {
        $list['device_id'] = FALSE;
    }
    // Hide entity_type if we know the alert_test_id
    if (isset($vars['alert_test_id']) || TRUE) {
        $list['entity_type'] = FALSE;
    }
    // Hide entity types in favour of icons to save space
    if ($vars['pagination'] && !$short) {
        $pagination_html = pagination($vars, $count);
        echo $pagination_html;
    }
    echo generate_box_open($vars['header']);
    echo '<table class="table table-condensed  table-striped  table-hover">';
    if ($vars['no_header'] == FALSE) {
        echo '
  <thead>
    <tr>
      <th class="state-marker"></th>
      <th style="width: 1px;"></th>';
        if ($list['device_id']) {
            echo '      <th style="width: 15%">Device</th>';
        }
        if ($list['entity_type']) {
            echo '      <th style="width: 10%">Type</th>';
        }
        if ($list['entity_id']) {
            echo '      <th style="">Entity</th>';
        }
        if ($list['alert_test_id']) {
            echo '      <th style="min-width: 15%;">Alert</th>';
        }
        echo '
      <th style="width: 100px;">Status</th>';
        if ($list['checked']) {
            echo '      <th style="width: 95px;">Checked</th>';
        }
        if ($list['changed']) {
            echo '      <th style="width: 95px;">Changed</th>';
        }
        if ($list['alerted']) {
            echo '      <th style="width: 95px;">Alerted</th>';
        }
        echo '    <th style="width: 45px;"></th>
    </tr>
  </thead>';
    }
    echo '<tbody>' . PHP_EOL;
    foreach ($alerts as $alert) {
        // Process the alert entry, generating colours and classes from the data
        humanize_alert_entry($alert);
        // Get the entity array using the cache
        $entity = get_entity_by_id_cache($alert['entity_type'], $alert['entity_id']);
        // Get the device array using the cache
        $device = device_by_id_cache($alert['device_id']);
        // Get the entity_name.
        ### FIXME - This is probably duplicated effort from above. We should pass it $entity
        $entity_name = entity_name($alert['entity_type'], $entity);
        // Set the alert_rule from the prebuilt cache array
        $alert_rule = $alert_rules[$alert['alert_test_id']];
        echo '<tr class="' . $alert['html_row_class'] . '" style="cursor: pointer;" onclick="openLink(\'' . generate_url(array('page' => 'device', 'device' => $device['device_id'], 'tab' => 'alert', 'alert_entry' => $alert['alert_table_id'])) . '\')">';
        echo '<td class="state-marker"></td>';
        echo '<td style="width: 1px;"></td>';
        // If we know the device, don't show the device
        if ($list['device_id']) {
            echo '<td><span class="entity-title">' . generate_device_link($device) . '</span></td>';
        }
        // If we're showing all entity types, print the entity type here
        if ($list['entity_type']) {
            echo '<td>' . nicecase($alert['entity_type']) . '</td>';
        }
        // Print a link to the entity
        if ($list['entity_id']) {
            echo '<td><span class="entity-title"><i class="' . $config['entities'][$alert['entity_type']]['icon'] . '"></i> ' . generate_entity_link($alert['entity_type'], $alert['entity_id']) . '</span></td>';
        }
        // Print link to the alert rule page
        if ($list['alert_test_id']) {
            echo '<td class="entity"><a href="', generate_url(array('page' => 'alert_check', 'alert_test_id' => $alert_rule['alert_test_id'])), '">', escape_html($alert_rule['alert_name']), '</a></td>';
        }
        echo '<td>';
        echo '<span class="label label-' . ($alert['html_row_class'] != 'up' ? $alert['html_row_class'] : 'success') . '">' . generate_tooltip_link('', $alert['status'], '<div class="small" style="max-width: 500px;"><strong>' . $alert['last_message'] . '</strong></div>', $alert['alert_class']) . '</span>';
        echo '</td>';
        // echo('<td class="'.$alert['class'].'">'.$alert['last_message'].'</td>');
        if ($list['checked']) {
            echo '<td>' . generate_tooltip_link('', $alert['checked'], format_unixtime($alert['last_checked'], 'r')) . '</td>';
        }
        if ($list['changed']) {
            echo '<td>' . generate_tooltip_link('', $alert['changed'], format_unixtime($alert['last_changed'], 'r')) . '</td>';
        }
        if ($list['alerted']) {
            echo '<td>' . generate_tooltip_link('', $alert['alerted'], format_unixtime($alert['last_alerted'], 'r')) . '</td>';
        }
        echo '<td>';
        // This stuff should go in an external entity popup in the future.
        $state = json_decode($alert['state'], true);
        $alert['state_popup'] = '';
        if (count($state['failed'])) {
            $alert['state_popup'] .= generate_box_open(array('title' => 'Failed Tests'));
            //'<h4>Failed Tests</h4>';
            $alert['state_popup'] .= '<table style="min-width: 400px;" class="table   table-striped table-condensed">';
            $alert['state_popup'] .= '<thead><tr><th>Metric</th><th>Cond</th><th>Value</th><th>Measured</th></tr></thead>';
            foreach ($state['failed'] as $test) {
                $alert['state_popup'] .= '<tr><td><strong>' . $test['metric'] . '</strong></td><td>' . $test['condition'] . '</td><td>' . $test['value'] . '</td><td><i class="red">' . $state['metrics'][$test['metric']] . '</i></td></tr>';
            }
            $alert['state_popup'] .= '</table>';
            $alert['state_popup'] .= generate_box_close();
        }
        $alert['state_popup'] .= generate_entity_popup_graphs($alert, array('entity_type' => 'alert_entry'));
        // Print (i) icon with popup of state.
        echo overlib_link("", '<i class="icon-info-sign text-primary"></i>', $alert['state_popup'], NULL);
        echo '&nbsp;&nbsp;<a href="' . generate_url(array('page' => 'device', 'device' => $device['device_id'], 'tab' => 'alert', 'alert_entry' => $alert['alert_table_id'])) . '"><i class="icon-cog text-muted"></i></a>';
        echo '</td>';
        echo '</tr>';
    }
    echo '  </tbody>' . PHP_EOL;
    echo '</table>' . PHP_EOL;
    echo generate_box_close();
    if ($vars['pagination'] && !$short) {
        echo $pagination_html;
    }
}
예제 #6
0
    print_error_permission();
    return;
}
// Export or save templates
$templates_export = FALSE;
if ($vars['saveas'] == 'yes') {
    $templates_export = $vars['filename'];
} else {
    if ($vars['export'] == 'yes') {
        $templates_export = 'print';
    }
}
unset($vars['export'], $vars['saveas'], $vars['filename']);
include $config['html_dir'] . "/includes/alerting-navbar.inc.php";
// Page to display list of configured alert checks
$alert_check = cache_alert_rules($vars);
#$alert_assoc = cache_alert_assoc($vars);
$where = ' WHERE 1' . generate_query_permitted(array('alert'));
// Build header menu
foreach (dbFetchRows("SELECT * FROM `alert_assoc` WHERE 1") as $entry) {
    $alert_assoc[$entry['alert_test_id']][$entry['alert_assoc_id']]['entity_type'] = $entry['entity_type'];
    $alert_assoc[$entry['alert_test_id']][$entry['alert_assoc_id']]['entity_attribs'] = json_decode($entry['entity_attribs'], TRUE);
    $alert_assoc[$entry['alert_test_id']][$entry['alert_assoc_id']]['device_attribs'] = json_decode($entry['device_attribs'], TRUE);
}
$navbar['class'] = "navbar-narrow";
$navbar['brand'] = "Alert Checks";
$types = dbFetchRows("SELECT DISTINCT `entity_type` FROM `alert_table`" . $where);
$navbar['options']['all']['url'] = generate_url($vars, array('page' => 'alert_checks', 'entity_type' => NULL));
$navbar['options']['all']['text'] = escape_html(nicecase('all'));
if (!isset($vars['entity_type'])) {
    $navbar['options']['all']['class'] = "active";
$navbar['options']['all']['text'] = escape_html(nicecase('全部'));
if ($vars['entity_type'] == 'all') {
    $navbar['options']['all']['class'] = "active";
    $navbar['options']['all']['url'] = generate_url($vars, array('page' => 'alerts', 'entity_type' => NULL));
}
foreach ($types as $thing) {
    if ($vars['entity_type'] == $thing['entity_type']) {
        $navbar['options'][$thing['entity_type']]['class'] = "active";
        $navbar['options'][$thing['entity_type']]['url'] = generate_url($vars, array('page' => 'alerts', 'entity_type' => NULL));
    } else {
        $navbar['options'][$thing['entity_type']]['url'] = generate_url($vars, array('page' => 'alerts', 'entity_type' => $thing['entity_type']));
    }
    $navbar['options'][$thing['entity_type']]['text'] = escape_html(nicecase($thing['entity_type']));
}
$navbar['options_right']['status']['url'] = generate_url($vars, array('page' => 'alerts', 'status' => 'failed'));
$navbar['options_right']['status']['text'] = '仅显示失败报警';
$navbar['options_right']['status']['icon'] = 'oicon-exclamation-red';
if ($vars['status'] == 'failed') {
    $navbar['options_right']['status']['class'] = 'active';
    $navbar['options_right']['status']['url'] = generate_url($vars, array('page' => 'alerts', 'status' => 'all'));
}
// Print out the navbar defined above
print_navbar($navbar);
// Cache the alert_tests table for use later
$alert_rules = cache_alert_rules($vars);
// Print out a table of alerts matching $vars
if ($vars['status'] != 'failed') {
    $vars['pagination'] = TRUE;
}
print_alert_table($vars);
// EOF
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);
}