1<?php
2/**
3 * Observium
4 *
5 *   This file is part of Observium.
6 *
7 * @package    observium
8 * @subpackage entities
9 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited
10 *
11 *
12 */
13
14/**
15 * Return normalized state array by type, mib and value (numeric or string)
16 *
17 * @param string $type        State type, in MIBs definition array $config['mibs'][$mib]['states'][$type]
18 * @param string $value       Polled value for status
19 * @param string $mib         MIB name
20 * @param string $event_map   Polled value for event (this used only for statuses with event condition values)
21 * @param string $poller_type Poller type (snmp, ipmi, agent)
22 *
23 * @return array State array
24 */
25function get_state_array($type, $value, $mib = '', $event_map = NULL, $poller_type = 'snmp')
26{
27  global $config;
28
29  $state_array = array('value' => FALSE);
30
31  switch ($poller_type)
32  {
33    case 'agent':
34    case 'ipmi':
35      $state = state_string_to_numeric($type, $value, $mib, $poller_type);
36      if ($state !== FALSE)
37      {
38        $state_array['value'] = $state; // Numeric value
39        $state_array['name']  = $config[$poller_type]['states'][$type][$state]['name'];  // Named value
40        $state_array['event'] = $config[$poller_type]['states'][$type][$state]['event']; // Event type
41        $state_array['mib']   = $mib;
42      }
43      break;
44
45    default: // SNMP
46      $state = state_string_to_numeric($type, $value, $mib);
47      if ($state !== FALSE)
48      {
49        if (!strlen($mib))
50        {
51          $mib = state_type_to_mib($type);
52        }
53        $state_array['value'] = $state; // Numeric value
54        $state_array['name']  = $config['mibs'][$mib]['states'][$type][$state]['name'];  // Named value
55
56        if (isset($config['mibs'][$mib]['states'][$type][$state]['event_map']))
57        {
58          // For events based on additional Oid value, see:
59          // PowerNet-MIB::emsInputContactStatusInputContactState.1 = INTEGER: contactOpenEMS(2)
60          // PowerNet-MIB::emsInputContactStatusInputContactNormalState.1 = INTEGER: normallyOpenEMS(2)
61
62          // Find event associated event with event_value
63          $state_array['event'] = $config['mibs'][$mib]['states'][$type][$state]['event_map'][$event_map];
64
65        } else {
66          // Normal static events
67          $state_array['event'] = $config['mibs'][$mib]['states'][$type][$state]['event']; // Event type
68        }
69        $state_array['mib']   = $mib; // MIB name
70      }
71  }
72
73  return $state_array;
74}
75
76/**
77 * Converts named oid values to numerical interpretation based on oid descriptions and stored in definitions
78 *
79 * @param string $type Sensor type which has definitions in $config['mibs'][$mib]['states'][$type]
80 * @param mixed $value Value which must be converted
81 * @param string $mib MIB name
82 * @param string $poller_type Poller type
83 *
84 * @return integer Note, if definition not found or incorrect value, returns FALSE
85 */
86function state_string_to_numeric($type, $value, $mib = '', $poller_type = 'snmp')
87{
88  switch ($poller_type)
89  {
90    case 'agent':
91    case 'ipmi':
92      if (!isset($GLOBALS['config'][$poller_type]['states'][$type]))
93      {
94        return FALSE;
95      }
96      $state_def = $GLOBALS['config'][$poller_type]['states'][$type];
97      break;
98
99    default:
100      if (!strlen($mib))
101      {
102        $mib = state_type_to_mib($type);
103      }
104      $state_def = $GLOBALS['config']['mibs'][$mib]['states'][$type];
105  }
106
107  if (is_numeric($value))
108  {
109    // Return value if already numeric
110    if ($value == (int)$value && isset($state_def[(int)$value]))
111    {
112      return (int)$value;
113    } else {
114      return FALSE;
115    }
116  }
117  foreach ($state_def as $index => $content)
118  {
119    if (strcasecmp($content['name'], trim($value)) == 0) { return $index; }
120  }
121
122  return FALSE;
123}
124
125/**
126 * Helper function for get MIB name by status type.
127 * Currently we use unique status types over all MIBs
128 *
129 * @param string $state_type Unique status type
130 *
131 * @return string MIB name corresponding to this type
132 */
133function state_type_to_mib($state_type)
134{
135  // By first cache all type -> mib from definitions
136  if (!isset($GLOBALS['cache']['state_type_mib']))
137  {
138    $GLOBALS['cache']['state_type_mib'] = array();
139    // $config['mibs'][$mib]['states']['dskf-mib-hum-state'][0] = array('name' => 'error',    'event' => 'alert');
140    foreach ($GLOBALS['config']['mibs'] as $mib => $entries)
141    {
142      if (!isset($entries['states'])) { continue; }
143      foreach ($entries['states'] as $type => $entry)
144      {
145        if (isset($GLOBALS['cache']['state_type_mib'][$type]))
146        {
147          // Disabling because it's annoying for now - pending some rewriting.
148          //print_warning('Warning, status type name "'.$type.'" for MIB "'.$mib.'" also exist in MIB "'.$GLOBALS['cache']['state_type_mib'][$type].'". Type name MUST be unique!');
149        }
150        $GLOBALS['cache']['state_type_mib'][$type] = $mib;
151      }
152    }
153  }
154
155  //print_vars($GLOBALS['cache']['state_type_mib']);
156  return $GLOBALS['cache']['state_type_mib'][$state_type];
157}
158
159function discover_status_definition($device, $mib, $entry)
160{
161
162  echo($entry['oid']. ' [');
163
164  // Check that types listed in skip_if_valid_exist have already been found
165  if (discovery_check_if_type_exist($GLOBALS['valid'], $entry, 'status')) { echo '!]'; return; }
166
167  // Check array requirements list
168  if (discovery_check_requires_pre($device, $entry, 'status')) { echo '!]'; return; }
169
170  // Fetch table or Oids
171  $table_oids = array('oid', 'oid_descr', 'oid_class', 'oid_map', 'oid_extra', 'oid_entPhysicalIndex');
172  $status_array = discover_fetch_oids($device, $mib, $entry, $table_oids);
173
174  if (empty($entry['oid_num']))
175  {
176    // Use snmptranslate if oid_num not set
177    $entry['oid_num'] = snmp_translate($entry['oid'], $mib);
178  } else {
179    $entry['oid_num'] = rtrim($entry['oid_num'], '.');
180  }
181
182  $i = 0; // Used in descr as $i++
183  $status_count = count($status_array);
184  foreach ($status_array as $index => $status)
185  {
186    $options = array();
187
188    $dot_index = '.' . $index;
189    $oid_num   = $entry['oid_num'] . $dot_index;
190
191    //echo PHP_EOL; print_vars($entry); echo PHP_EOL; print_vars($status); echo PHP_EOL; print_vars($descr); echo PHP_EOL;
192
193    // %i% can be used in description
194    $i++;
195
196    if (isset($entry['oid_class']) && strlen($status[$entry['oid_class']]))
197    {
198      if (isset($entry['map_class'][$status[$entry['oid_class']]]))
199      {
200        // Try override measured class by map
201        $class = $entry['map_class'][$status[$entry['oid_class']]];
202        if ($class == 'exclude' || !$class)
203        {
204          print_debug("Excluded by empty class map value.");
205          continue; // trigger for exclude statuses
206        }
207      } else {
208        $class = $status[$entry['oid_class']];
209      }
210    } else {
211      $class = $entry['measured'];
212    }
213    // Generate specific keys used during rewrites
214
215    $status['class'] = nicecase($class); // Class in descr
216    $status['index'] = $index;           // Index in descr
217    $status['i']     = $i;               // i++ counter in descr
218
219    // Check array requirements list
220    if (discovery_check_requires($device, $entry, $status, 'status')) { continue; }
221
222    $value = $status[$entry['oid']];
223    if (!strlen($value))
224    {
225      print_debug("Excluded by empty current value.");
226      continue;
227    }
228
229    $options = array('entPhysicalClass' => $class);
230
231    // Definition based events
232    if (isset($entry['oid_map']) && $status[$entry['oid_map']])
233    {
234      $options['status_map'] = $status[$entry['oid_map']];
235    }
236
237    // Rule-based entity linking.
238    if ($measured = entity_measured_match_definition($device, $entry, $status, 'status'))
239    {
240      $options = array_merge($options, $measured);
241      $status  = array_merge($status, $measured); // append to $status for %descr% tags, ie %port_label%
242      if (empty($class))
243      {
244        $options['entPhysicalClass'] = $measured['measured'];
245      }
246    }
247    // End rule-based entity linking
248    else if (isset($entry['entPhysicalIndex']))
249    {
250      // Just set physical index
251      $options['entPhysicalIndex'] = array_tag_replace($status, $entry['entPhysicalIndex']);
252    }
253
254    // Generate Description
255    $descr = entity_descr_definition('status', $entry, $status, $status_count);
256
257    // Rename old (converted) RRDs to definition format
258    if (isset($entry['rename_rrd']))
259    {
260      $options['rename_rrd'] = $entry['rename_rrd'];
261    }
262    else if (isset($entry['rename_rrd_full']))
263    {
264      $options['rename_rrd_full'] = $entry['rename_rrd_full'];
265    }
266
267    discover_status_ng($device, $mib, $entry['oid'], $oid_num, $index, $entry['type'], $descr, $value, $options);
268
269  }
270
271  echo '] ';
272
273}
274
275// Compatibility wrapper!
276function discover_status($device, $numeric_oid, $index, $type, $status_descr, $value = NULL, $options = array(), $poller_type = NULL)
277{
278  if (isset($poller_type)) { $options['poller_type'] = $poller_type; }
279
280  return discover_status_ng($device, '', '', $numeric_oid, $index, $type, $status_descr, $value, $options);
281}
282
283// TESTME needs unit testing
284/**
285 * Discover a new status sensor on a device - called from discover_sensor()
286 *
287 * This function adds a status sensor to a device, if it does not already exist.
288 * Data on the sensor is updated if it has changed, and an event is logged with regards to the changes.
289 *
290 * @param array $device        Device array status sensor is being discovered on
291 * @param string $mib          SNMP MIB name
292 * @param string $object       SNMP Named Oid of sensor (without index)
293 * @param string $oid          SNMP Numeric Oid of sensor (without index)
294 * @param string $index        SNMP index of status sensor
295 * @param string $type         Type of status sensor (used as key in $config['status_states'])
296 * @param string $status_descr Description of status sensor
297 * @param string $value        Current value of status sensor
298 * @param array $options       Options
299 *
300 * @return bool
301 */
302function discover_status_ng($device, $mib, $object, $oid, $index, $type, $status_descr, $value = NULL, $options = array())
303{
304  global $config;
305
306  $poller_type   = (isset($options['poller_type']) ? $options['poller_type'] : 'snmp');
307
308  $status_deleted = 0;
309
310  // Init main
311  $param_main = array('oid' => 'status_oid', 'status_descr' => 'status_descr', 'status_deleted' => 'status_deleted',
312                      'index' => 'status_index', 'mib' => 'status_mib', 'object' => 'status_object');
313
314  // Init optional
315  $param_opt = array('entPhysicalIndex', 'entPhysicalClass', 'entPhysicalIndex_measured', 'measured_class', 'measured_entity', 'status_map');
316  foreach ($param_opt as $key)
317  {
318    $$key = ($options[$key] ? $options[$key] : NULL);
319  }
320
321  $state_array = get_state_array($type, $value, $mib, $status_map, $poller_type);
322  $state = $state_array['value'];
323  if ($state === FALSE)
324  {
325    print_debug("Skipped by unknown state value: $value, $status_descr ");
326    return FALSE;
327  }
328  else if ($state_array['event'] == 'exclude')
329  {
330    print_debug("Skipped by 'exclude' event value: ".$config['status_states'][$type][$state]['name'].", $status_descr ");
331    return FALSE;
332  }
333  $value = $state;
334  $index = strval($index); // Convert to string, for correct compare
335
336  print_debug("Discover status: [device: ".$device['hostname'].", oid: $oid, index: $index, type: $type, descr: $status_descr, CURRENT: $value, $entPhysicalIndex, $entPhysicalClass]");
337
338  // Check sensor ignore filters
339  foreach ($config['ignore_sensor'] as $bi)        { if (strcasecmp($bi, $status_descr) == 0)   { print_debug("Skipped by equals: $bi, $status_descr "); return FALSE; } }
340  foreach ($config['ignore_sensor_string'] as $bi) { if (stripos($status_descr, $bi) !== FALSE) { print_debug("Skipped by strpos: $bi, $status_descr "); return FALSE; } }
341  foreach ($config['ignore_sensor_regexp'] as $bi) { if (preg_match($bi, $status_descr) > 0)    { print_debug("Skipped by regexp: $bi, $status_descr "); return FALSE; } }
342
343  $new_definition = $poller_type == 'snmp' && strlen($mib) && strlen($object);
344  if ($new_definition)
345  {
346    $where  = ' WHERE `device_id` = ? AND `status_mib` = ? AND `status_object` = ? AND `status_type` = ? AND `status_index` = ? AND `poller_type`= ?';
347    $params = array($device['device_id'], $mib, $object, $type, $index, $poller_type);
348    $status_exist = dbExist('status', $where, $params);
349
350    // Check if old format of status was exist, than rename rrd
351    if (!$status_exist)
352    {
353      $old_where  = ' WHERE `device_id` = ? AND `status_type` = ? AND `status_index` = ? AND `poller_type`= ?';
354      $old_index  = $object . '.' . $index;
355      $old_params = array($device['device_id'], $type, $old_index, $poller_type);
356
357      if ($status_exist = dbExist('status', $old_where, $old_params))
358      {
359        $where        = $old_where;
360        $params       = $old_params;
361
362        // Rename old rrds without mib & object to new rrd name style
363        if (!isset($options['rename_rrd']))
364        {
365          $options['rename_rrd'] = $type . "-" . $old_index;
366        }
367      }
368    }
369  } else {
370    // Old format of definitions
371    $where  = ' WHERE `device_id` = ? AND `status_type` = ? AND `status_index` = ? AND `poller_type`= ?';
372    $params = array($device['device_id'], $type, $index, $poller_type);
373    $status_exist = dbExist('status', $where, $params);
374  }
375  //if (dbFetchCell('SELECT COUNT(*) FROM `status`' . $where, $params) == '0')
376  if (!$status_exist)
377  {
378    $status_insert = array('poller_type'  => $poller_type,
379                           'device_id'    => $device['device_id'],
380                           'status_index' => $index,
381                           'status_type'  => $type,
382                           //'status_id'    => $status_id,
383                           'status_value' => $value,
384                           'status_polled' => time(), //array('NOW()'), // this field is INT(11)
385                           'status_event' => $state_array['event'],
386                           'status_name'  => $state_array['name']
387    );
388
389    foreach ($param_main as $key => $column)
390    {
391      $status_insert[$column] = $$key;
392    }
393
394    foreach ($param_opt as $key)
395    {
396      if (is_null($$key)) { $$key = array('NULL'); } // If param null, convert to array(NULL)
397      $status_insert[$key] = $$key;
398    }
399
400    $status_id = dbInsert($status_insert, 'status');
401
402    print_debug("( $status_id inserted )");
403    echo('+');
404    log_event("Status added: $entPhysicalClass $type $index $status_descr", $device, 'status', $status_id);
405  } else {
406    $status_entry = dbFetchRow('SELECT * FROM `status`' . $where, $params);
407    $status_id = $status_entry['status_id'];
408
409    print_debug_vars($status_entry);
410    $update = array();
411    foreach ($param_main as $key => $column)
412    {
413      if ($$key != $status_entry[$column])
414      {
415        $update[$column] = $$key;
416      }
417    }
418    foreach ($param_opt as $key)
419    {
420      if ($$key != $status_entry[$key])
421      {
422        $update[$key] = $$key;
423      }
424    }
425    print_debug_vars($update);
426
427    if (count($update))
428    {
429      $updated = dbUpdate($update, 'status', '`status_id` = ?', array($status_entry['status_id']));
430      echo('U');
431      log_event("Status updated: $entPhysicalClass $type $index $status_descr", $device, 'status', $status_entry['status_id']);
432    } else {
433      echo('.');
434    }
435  }
436
437  // Rename old (converted) RRDs to definition format
438  // Allow with changing class or without
439  if (isset($options['rename_rrd_full']))
440  {
441    // Compatibility with sensor option
442    $options['rename_rrd'] = $options['rename_rrd_full'];
443  }
444  if (isset($options['rename_rrd']))
445  {
446    $rrd_tags = array('index' => $index, 'type' => $type, 'mib' => $mib, 'object' => $object, 'oid' => $object);
447    $options['rename_rrd'] = array_tag_replace($rrd_tags, $options['rename_rrd']);
448    $old_rrd               = 'status-' . $options['rename_rrd'];
449
450    //$new_rrd = 'status-'.$type.'-'.$index;
451    $new_entry = ['status_descr' => $status_descr, 'status_mib' => $mib, 'status_object' => $object,
452                  'status_type' => $type, 'status_index' => $index, 'poller_type' => $poller_type];
453    $new_rrd = get_status_rrd($device, $new_entry);
454    rename_rrd($device, $old_rrd, $new_rrd);
455  }
456
457  if (strlen($mib))
458  {
459    $GLOBALS['valid']['status'][$mib][$type][$index] = 1;
460  } else {
461    $GLOBALS['valid']['status']['__'][$type][$index] = 1;
462  }
463
464  return $status_id;
465  //return TRUE;
466}
467
468// DOCME needs phpdoc block
469// TESTME needs unit testing
470function check_valid_status($device, $valid, $poller_type = 'snmp')
471{
472  $entries = dbFetchRows("SELECT * FROM `status` WHERE `device_id` = ? AND `poller_type` = ? AND `status_deleted` = '0'", array($device['device_id'], $poller_type));
473
474  if (is_array($entries) && count($entries))
475  {
476    foreach ($entries as $entry)
477    {
478      $index = $entry['status_index'];
479      $type  = $entry['status_type'];
480      $mib   = strlen($entry['status_mib']) ? $entry['status_mib'] : '__';
481      if (!$valid[$mib][$type][$index])
482      {
483        echo("-");
484        print_debug("Status deleted: $index -> $type");
485        //dbDelete('status',       "`status_id` = ?", array($entry['status_id']));
486        //dbDelete('status-state', "`status_id` = ?", array($entry['status_id']));
487
488        dbUpdate(array('status_deleted' => '1'), 'status', '`status_id` = ?', array($entry['status_id']));
489
490        foreach (get_entity_attribs('status', $entry['status_id']) as $attrib_type => $value)
491        {
492          del_entity_attrib('status', $entry['status_id'], $attrib_type);
493        }
494        log_event("Status deleted: ".$entry['status_class']." ".$entry['status_type']." ". $entry['status_index']." ".$entry['status_descr'], $device, 'status', $entry['status_id']);
495      }
496    }
497  }
498}
499
500function poll_status($device, &$oid_cache)
501{
502  global $config, $agent_sensors, $ipmi_sensors, $graphs, $table_rows;
503
504  $sql  = "SELECT * FROM `status`";
505  //$sql .= " LEFT JOIN `status-state` USING(`status_id`)";
506  $sql .= " WHERE `device_id` = ? AND `status_deleted` = ?";
507  $sql .= ' ORDER BY `status_oid`'; // This fix polling some OIDs (when not ordered)
508
509  foreach (dbFetchRows($sql, array($device['device_id'], '0')) as $status_db)
510  {
511    //print_cli_heading("Status: ".$status_db['status_descr']. "(".$status_db['poller_type'].")", 3);
512
513    print_debug("Checking (" . $status_db['poller_type'] . ") " . $status_db['status_descr'] . " ");
514
515    // $status_poll = $status_db;    // Cache non-humanized status array for use as new status state
516
517    if ($status_db['poller_type'] == "snmp")
518    {
519      $status_db['status_oid'] = '.' . ltrim($status_db['status_oid'], '.'); // Fix first dot in oid for caching
520
521      // Check if a specific poller file exists for this status, else collect via SNMP.
522      $file = $config['install_dir']."/includes/polling/status/".$status_db['status_type'].".inc.php";
523
524      if (is_file($file))
525      {
526        include($file);
527      } else {
528        // Take value from $oid_cache if we have it, else snmp_get it
529        if (isset($oid_cache[$status_db['status_oid']]))
530        {
531          print_debug("value taken from oid_cache");
532          $status_value = $oid_cache[$status_db['status_oid']];
533        } else {
534          $status_value = snmp_get_oid($device, $status_db['status_oid'], 'SNMPv2-MIB');
535        }
536        //$status_value = snmp_fix_numeric($status_value); // Do not use fix, this broke not-enum (string) statuses
537      }
538    }
539    else if ($status_db['poller_type'] == "agent")
540    {
541      if (isset($agent_sensors['state']))
542      {
543        $status_value = $agent_sensors['state'][$status_db['status_type']][$status_db['status_index']]['current'];
544      } else {
545        print_warning("No agent status data available.");
546        continue;
547      }
548    }
549    else if ($status_db['poller_type'] == "ipmi")
550    {
551      if (isset($ipmi_sensors['state']))
552      {
553        $status_value = $ipmi_sensors['state'][$status_db['status_type']][$status_db['status_index']]['current'];
554      } else {
555        print_warning("No IPMI status data available.");
556        continue;
557      }
558    } else {
559      print_warning("Unknown status poller type.");
560      continue;
561    }
562
563    $status_polled_time = time(); // Store polled time for current status
564
565    // Write new value and humanize (for alert checks)
566    $state_array = get_state_array($status_db['status_type'], $status_value, $status_db['status_mib'], $status_db['status_map'], $status_db['poller_type']);
567    $status_value                = $state_array['value']; // Override status_value by numeric for "pseudo" (string) statuses
568    $status_poll['status_value'] = $state_array['value'];
569    $status_poll['status_name']  = $state_array['name'];
570    if ($status_db['status_ignore'] || $status_db['status_disable'])
571    {
572      $status_poll['status_event'] = 'ignore';
573    } else {
574      $status_poll['status_event'] = $state_array['event'];
575    }
576
577    // If last change never set, use current time
578    if (empty($status_db['status_last_change']))
579    {
580      $status_db['status_last_change'] = $status_polled_time;
581    }
582
583    if ($status_poll['status_event'] != $status_db['status_event'])
584    {
585      // Status event changed, log and set status_last_change
586      $status_poll['status_last_change'] = $status_polled_time;
587
588      if ($status_poll['status_event'] == 'ignore')
589      {
590        print_message("[%ystatus Ignored%n]", 'color');
591      }
592      else if ($status_db['status_event'] != '')
593      {
594        // If old state not empty and new state not equals to new state
595        $msg = 'Status ' . ucfirst($status_poll['status_event']) . ': ' . $device['hostname'] . ' ' . $status_db['status_descr'] .
596          ' entered ' . strtoupper($status_poll['status_event']) . ' state: ' . $status_poll['status_name'] .
597          ' (previous: ' . $status_db['status_name'] . ')';
598
599        if (isset($config['entity_events'][$status_poll['status_event']]))
600        {
601          $severity = $config['entity_events'][$status_poll['status_event']]['severity'];
602        } else {
603          $severity = 'informational';
604        }
605        log_event($msg, $device, 'status', $status_db['status_id'], $severity);
606
607      }
608    } else {
609      // If status not changed, leave old last_change
610      $status_poll['status_last_change'] = $status_db['status_last_change'];
611    }
612
613    print_debug_vars($status_poll);
614
615    // Send statistics array via AMQP/JSON if AMQP is enabled globally and for the ports module
616    if ($config['amqp']['enable'] == TRUE && $config['amqp']['modules']['status'])
617    {
618      $json_data = array('value' => $status_value);
619      messagebus_send(array('attribs' => array('t' => time(), 'device' => $device['hostname'], 'device_id' => $device['device_id'],
620                                               'e_type' => 'status', 'e_type' => $status_db['status_type'], 'e_index' => $status_db['status_index']), 'data' => $json_data));
621    }
622
623    // Update StatsD/Carbon
624    if ($config['statsd']['enable'] == TRUE)
625    {
626      StatsD::gauge(str_replace(".", "_", $device['hostname']).'.'.'status'.'.'.$status_db['status_class'].'.'.$status_db['status_type'].'.'.$status_db['status_index'], $status_value);
627    }
628
629    // Update RRD - FIXME - can't convert to NG because filename is dynamic! new function should return index instead of filename.
630    $rrd_file = get_status_rrd($device, $status_db);
631    rrdtool_create($device, $rrd_file, "DS:status:GAUGE:600:-20000:U");
632    rrdtool_update($device, $rrd_file,"N:$status_value");
633
634    // Enable graph
635    $graphs[$status_db['status']] = TRUE;
636
637    // Check alerts
638    $metrics = array();
639
640    $metrics['status_value'] = $status_value;
641    $metrics['status_name']  = $status_poll['status_name'];
642    $metrics['status_name_uptime'] = $status_polled_time - $status_poll['status_last_change'];
643    $metrics['status_event'] = $status_poll['status_event'];
644
645    //print_cli_data("Event (State)", $status_poll['status_event'] ." (".$status_poll['status_name'].")", 3);
646
647    $table_rows[] = array($status_db['status_descr'], $status_db['status_type'], $status_db['status_index'] ,$status_db['poller_type'],
648                          $status_poll['status_name'], $status_poll['status_event'], format_unixtime($status_poll['status_last_change']));
649
650    check_entity('status', $status_db, $metrics);
651
652    // Add to MultiUpdate SQL State
653
654    $GLOBALS['multi_update_db'][] = array(
655      'status_id'          => $status_db['status_id'], // UNIQUE index
656      'status_value'       => $status_value,
657      'status_name'        => $status_poll['status_name'],
658      'status_event'       => $status_poll['status_event'],
659      'status_last_change' => $status_poll['status_last_change'],
660      'status_polled'      => $status_polled_time);
661    //dbUpdate(array('status_value'  => $status_value,
662    //               'status_name'   => $status_poll['status_name'],
663    //               'status_event'  => $status_poll['status_event'],
664    //               'status_last_change' => $status_poll['status_last_change'],
665    //               'status_polled' => $status_polled_time),
666    //               'status', '`status_id` = ?', array($status_db['status_id']));
667  }
668}
669
670// DOCME needs phpdoc block
671// TESTME needs unit testing
672function get_status_rrd($device, $status)
673{
674  global $config;
675
676  # For IPMI, sensors tend to change order, and there is no index, so we prefer to use the description as key here.
677  if ($config['os'][$device['os']]['status_descr'] || ($status['poller_type'] != "snmp" && $status['poller_type'] != ''))
678  {
679    $rrd_file = "status-" . $status['status_type'] . "-" . $status['status_descr'] . ".rrd";
680  }
681  elseif (strlen($status['status_mib']) && strlen($status['status_object']))
682  {
683    // for discover_status_ng(), note here is just status index
684    $rrd_file = "status-" . $status['status_mib'] . "-" . $status['status_object'] . "-" . $status['status_index'] . ".rrd";
685  } else {
686    // for discover_status(), note index == "%object%.%index%"
687    $rrd_file = "status-".$status['status_type']."-".$status['status_index'] . ".rrd";
688  }
689
690  return($rrd_file);
691}
692
693// EOF
694