2131 lines
76 KiB
PHP
2131 lines
76 KiB
PHP
<?php
|
|
/**
|
|
* Observium
|
|
*
|
|
* This file is part of Observium.
|
|
*
|
|
* @package observium
|
|
* @subpackage entities
|
|
* @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited
|
|
*
|
|
*/
|
|
|
|
// Include entity specific functions
|
|
require_once($config['install_dir'] . "/includes/entities/device.inc.php");
|
|
require_once($config['install_dir'] . "/includes/entities/port.inc.php");
|
|
require_once($config['install_dir'] . "/includes/entities/storage.inc.php");
|
|
require_once($config['install_dir'] . "/includes/entities/sensor.inc.php");
|
|
require_once($config['install_dir'] . "/includes/entities/status.inc.php");
|
|
require_once($config['install_dir'] . "/includes/entities/counter.inc.php");
|
|
if (OBSERVIUM_EDITION !== 'community') {
|
|
include_once($config['install_dir'] . "/includes/entities/probe.inc.php");
|
|
}
|
|
require_once($config['install_dir'] . "/includes/entities/ip-address.inc.php");
|
|
require_once($config['install_dir'] . "/includes/entities/routing.inc.php");
|
|
require_once($config['install_dir'] . "/includes/entities/wifi.inc.php");
|
|
|
|
/**
|
|
*
|
|
* Get attribute value for entity
|
|
*
|
|
* @param string $entity_type
|
|
* @param mixed $entity_id
|
|
* @param string $attrib_type
|
|
* @return string
|
|
*/
|
|
function get_entity_attrib($entity_type, $entity_id, $attrib_type) {
|
|
if (is_array($entity_id)) {
|
|
// Passed entity array, instead id
|
|
$translate = entity_type_translate_array($entity_type);
|
|
$entity_id = $entity_id[$translate['id_field']];
|
|
}
|
|
if (!$entity_id) { return NULL; }
|
|
|
|
if (isset($GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id]) &&
|
|
array_key_exists($attrib_type, $GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id])) {
|
|
return $GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id][$attrib_type];
|
|
}
|
|
if (isset($GLOBALS['cache']['entity_attribs_all'][$entity_type][$entity_id])) {
|
|
// when all entity attribs already cached, but specified attrib not exist, prevent extra db query
|
|
return NULL;
|
|
}
|
|
|
|
if ($row = dbFetchRow("SELECT `attrib_value` FROM `entity_attribs` WHERE `entity_type` = ? AND `entity_id` = ? AND `attrib_type` = ?", [ $entity_type, $entity_id, $attrib_type ])) {
|
|
return $row['attrib_value'];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Get all attributes for entity
|
|
*
|
|
* @param string $entity_type
|
|
* @param mixed $entity_id
|
|
* @return array
|
|
*/
|
|
function get_entity_attribs($entity_type, $entity_id, $refresh = FALSE) {
|
|
if (is_array($entity_id)) {
|
|
if (isset($entity_id['device_id']) && is_intnum($entity_id['device_id'])) {
|
|
$device_id = $entity_id['device_id'];
|
|
|
|
// Pre-check if entity attribs for device exist
|
|
cache_device_attribs_exist($device_id, $refresh);
|
|
// if ($refresh || !isset($GLOBALS['cache']['devices_attribs'][$device_id][$entity_type])) {
|
|
// $GLOBALS['cache']['devices_attribs'][$device_id][$entity_type] = dbExist('entity_attribs', '`entity_type` = ? AND `device_id` = ?', [ $entity_type, $device_id ]);
|
|
// }
|
|
// Speedup queries, when not exist attribs
|
|
if (!isset($GLOBALS['cache']['devices_attribs'][$device_id][$entity_type]) ||
|
|
!$GLOBALS['cache']['devices_attribs'][$device_id][$entity_type]) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// Passed entity array, instead id
|
|
$translate = entity_type_translate_array($entity_type);
|
|
$entity_id = $entity_id[$translate['id_field']];
|
|
}
|
|
|
|
if (!$entity_id) { return NULL; }
|
|
|
|
if ($refresh || !isset($GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id])) {
|
|
|
|
if (isset($device_id)) {
|
|
foreach (dbFetchRows("SELECT * FROM `entity_attribs` WHERE `entity_type` = ? AND `device_id` = ?", [ $entity_type, $device_id ]) as $entry) {
|
|
$GLOBALS['cache']['entity_attribs'][$entity_type][$entry['entity_id']][$entry['attrib_type']] = $entry['attrib_value'];
|
|
|
|
// Set a logical sign that all attributes are cached, for get_entity_attrib()
|
|
$GLOBALS['cache']['entity_attribs_all'][$entity_type][$entry['entity_id']] = TRUE;
|
|
}
|
|
|
|
} else {
|
|
$attribs = [];
|
|
foreach (dbFetchRows("SELECT * FROM `entity_attribs` WHERE `entity_type` = ? AND `entity_id` = ?", [ $entity_type, $entity_id ]) as $entry) {
|
|
$attribs[$entry['attrib_type']] = $entry['attrib_value'];
|
|
}
|
|
|
|
$GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id] = $attribs;
|
|
// Set a logical sign that all attributes are cached, for get_entity_attrib()
|
|
$GLOBALS['cache']['entity_attribs_all'][$entity_type][$entity_id] = TRUE;
|
|
}
|
|
}
|
|
return $GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id];
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Set value for specific attribute and entity
|
|
*
|
|
* @param string $entity_type
|
|
* @param mixed $entity_id
|
|
* @param string $attrib_type
|
|
* @param string $attrib_value
|
|
* @param string $device_id
|
|
* @return boolean
|
|
*/
|
|
function set_entity_attrib($entity_type, $entity_id, $attrib_type, $attrib_value, $device_id = NULL) {
|
|
if (is_array($entity_id)) {
|
|
// Passed entity array, instead id
|
|
$translate = entity_type_translate_array($entity_type);
|
|
$entity = $entity_id;
|
|
$entity_id = $entity[$translate['id_field']];
|
|
}
|
|
|
|
if (!$entity_id) { return NULL; }
|
|
|
|
// If we're setting a device attribute, use the entity_id as the device_id
|
|
if ($entity_type === "device") { $device_id = $entity_id; }
|
|
|
|
// If we don't have a device_id, try to work out what it should be
|
|
if (!$device_id) {
|
|
if (isset($entity) && isset($entity['device_id'])) {
|
|
$device_id = $entity['device_id'];
|
|
} else {
|
|
$entity = get_entity_by_id_cache($entity_type, $entity_id);
|
|
$device_id = $entity['device_id'];
|
|
}
|
|
}
|
|
if (!$device_id) {
|
|
print_error("Enable to set attrib data : $entity_type, $entity_id, $attrib_type, $attrib_value, $device_id");
|
|
return NULL;
|
|
}
|
|
|
|
// Reset cached entity attribs
|
|
if (isset($GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id])) {
|
|
unset($GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id]);
|
|
}
|
|
if (isset($GLOBALS['cache']['entity_attribs_all'][$entity_type][$entity_id])) {
|
|
unset($GLOBALS['cache']['entity_attribs_all'][$entity_type][$entity_id]);
|
|
}
|
|
|
|
//if (dbFetchCell("SELECT COUNT(*) FROM `entity_attribs` WHERE `entity_type` = ? AND `entity_id` = ? AND `attrib_type` = ?", array($entity_type, $entity_id, $attrib_type)))
|
|
if (dbExist('entity_attribs', '`entity_type` = ? AND `entity_id` = ? AND `attrib_type` = ?', array($entity_type, $entity_id, $attrib_type))) {
|
|
$return = dbUpdate(array('attrib_value' => $attrib_value), 'entity_attribs', '`entity_type` = ? AND `entity_id` = ? AND `attrib_type` = ?', array($entity_type, $entity_id, $attrib_type));
|
|
} else {
|
|
$return = dbInsert(array('device_id' => $device_id, 'entity_type' => $entity_type, 'entity_id' => $entity_id, 'attrib_type' => $attrib_type, 'attrib_value' => $attrib_value), 'entity_attribs');
|
|
if ($return !== FALSE) { $return = TRUE; } // Note dbInsert return IDs if exist or 0 for not indexed tables
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Delete specific attribute for entity
|
|
*
|
|
* @param string $entity_type
|
|
* @param mixed $entity_id
|
|
* @param string $attrib_type
|
|
* @return boolean
|
|
*/
|
|
function del_entity_attrib($entity_type, $entity_id, $attrib_type) {
|
|
if (is_array($entity_id)) {
|
|
// Passed entity array, instead id
|
|
$translate = entity_type_translate_array($entity_type);
|
|
$entity_id = $entity_id[$translate['id_field']];
|
|
}
|
|
if (!$entity_id) { return NULL; }
|
|
|
|
// Reset cached entity attribs
|
|
if (isset($GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id])) {
|
|
unset($GLOBALS['cache']['entity_attribs'][$entity_type][$entity_id]);
|
|
}
|
|
if (isset($GLOBALS['cache']['entity_attribs_all'][$entity_type][$entity_id])) {
|
|
unset($GLOBALS['cache']['entity_attribs_all'][$entity_type][$entity_id]);
|
|
}
|
|
|
|
return dbDelete('entity_attribs', '`entity_type` = ? AND `entity_id` = ? AND `attrib_type` = ?', array($entity_type, $entity_id, $attrib_type));
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Get array of entities (id) linked to device
|
|
*
|
|
* @param mixed $device_id Device array of id
|
|
* @param mixed $entity_types List of entities as array, if empty get all
|
|
* @return array
|
|
*/
|
|
function get_device_entities($device_id, $entity_types = NULL) {
|
|
if (is_array($device_id)) {
|
|
// Passed device array, instead id
|
|
$device_id = $device_id['device_id'];
|
|
}
|
|
if (!$device_id || $entity_types === FALSE) { return []; }
|
|
|
|
if (!is_array($entity_types) && !safe_empty($entity_types)) {
|
|
// Single entity type passed, convert to array
|
|
$entity_types = array($entity_types);
|
|
}
|
|
$all = safe_empty($entity_types);
|
|
$entities = [];
|
|
foreach (array_keys($GLOBALS['config']['entities']) as $entity_type) {
|
|
if ($all || in_array($entity_type, $entity_types, TRUE)) {
|
|
$translate = entity_type_translate_array($entity_type);
|
|
if (!$translate['device_id_field']) { continue; }
|
|
$query = 'SELECT `' . $translate['id_field'] . '` FROM `' . $translate['table'] . '` WHERE `' . $translate['device_id_field'] . '` = ?;';
|
|
$entity_ids = dbFetchColumn($query, [ $device_id ]);
|
|
if (safe_count($entity_ids)) {
|
|
$entities[$entity_type] = $entity_ids;
|
|
}
|
|
}
|
|
}
|
|
return $entities;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Get all attributes for all entities from device
|
|
*
|
|
* @param mixed $device_id
|
|
* @param mixed $entity_types
|
|
* @return array
|
|
*/
|
|
function get_device_entities_attribs($device_id, $entity_types = NULL)
|
|
{
|
|
$attribs = array();
|
|
|
|
$query = "SELECT * FROM `entity_attribs` WHERE `device_id` = ?";
|
|
if ($entity_types)
|
|
{
|
|
$query .= generate_query_values_and($entity_types, 'entity_type');
|
|
}
|
|
|
|
foreach (dbFetchRows($query, array($device_id)) as $entry)
|
|
{
|
|
$attribs[$entry['entity_type']][$entry['entity_id']][$entry['attrib_type']] = $entry['attrib_value'];
|
|
}
|
|
|
|
return $attribs;
|
|
}
|
|
|
|
/* MIB & object specific functions */
|
|
|
|
/**
|
|
* Check if MIB available and permitted for device
|
|
* if $check_permissions is TRUE, check permissions by config option $config['mibs'][$mib]
|
|
* and from the enable/disable panel in the device configuration in the web interface
|
|
* if $check_sysORID is TRUE, we fetch the device's supplied list as well - should only be FALSE in the sysORID code
|
|
*
|
|
* @param array $device Device array
|
|
* @param string|array $mib MIB name
|
|
* @param boolean $check_permissions Check device specific MIB permissions (if FALSE ignores it)
|
|
* @param boolean $check_sysORID Check if MIB exist in sysOROID table
|
|
*
|
|
* @return boolean MIB is permitted for device or not.
|
|
*/
|
|
function is_device_mib($device, $mib, $check_permissions = TRUE, $check_sysORID = TRUE) {
|
|
global $config;
|
|
|
|
if (is_array_list($mib)) {
|
|
// Recursive check multiple MIBs
|
|
$return = FALSE;
|
|
foreach ($mib as $entry) {
|
|
if ($return = is_device_mib($device, $entry, $check_permissions, $check_sysORID)) {
|
|
break;
|
|
}
|
|
}
|
|
return $return;
|
|
}
|
|
|
|
$mib_permitted = in_array($mib, get_device_mibs($device, $check_sysORID)); // Check if mib available for device
|
|
|
|
if ($check_permissions && $mib_permitted) {
|
|
// Check if MIB permitted by config
|
|
//$mib_permitted = $mib_permitted && (!isset($config['mibs'][$mib]['enable']) || $config['mibs'][$mib]['enable']);
|
|
if (isset($config['mibs'][$mib]['enable']) && !$config['mibs'][$mib]['enable']) {
|
|
// Globally disabled MIB with different logic
|
|
$where = "`device_id` = ? AND `use` = ? AND `mib` = ?";
|
|
$params = [ $device['device_id'], 'mib', $mib ];
|
|
$disabled = dbFetchCell("SELECT `disabled` FROM `devices_mibs` WHERE $where", $params);
|
|
$mib_permitted = $disabled === '0';
|
|
if (!$mib_permitted) {
|
|
print_debug("MIB [$mib] disabled in global config.");
|
|
} else {
|
|
print_debug("MIB [$mib] disabled in global config, but enabled in device config.");
|
|
}
|
|
return $mib_permitted;
|
|
}
|
|
// if (!$mib_permitted) {
|
|
// print_debug("MIB [$mib] disabled in global config.");
|
|
// return $mib_permitted;
|
|
// }
|
|
|
|
// Check if MIB disabled on device by web interface or polling process
|
|
$mibs_disabled = get_device_mibs_disabled($device);
|
|
$mib_permitted = $mib_permitted && !in_array($mib, $mibs_disabled);
|
|
if (OBS_DEBUG && !$mib_permitted) {
|
|
print_debug("MIB [$mib] disabled in device config.");
|
|
}
|
|
}
|
|
|
|
return $mib_permitted;
|
|
}
|
|
|
|
/**
|
|
* Return cached MIBs array available for device (from os definitions)
|
|
* By default includes sysORID-supplied MIBs unless check_sysORID is false
|
|
* When requesting list without sysORID, result will NOT be cached
|
|
*
|
|
* @param array|integer $device Device array
|
|
* @param bool $check_sysORID Check or not mibs from sysORID table (Note in 99.99% cases this used as TRUE)
|
|
* @param array|string $mibs_order Order how load available mibs. Default: [ 'model', 'os', 'group', 'default' ]
|
|
*
|
|
* @return array List of supported MIBs
|
|
*/
|
|
function get_device_mibs($device, $check_sysORID = TRUE, $mibs_order = NULL) {
|
|
global $config, $cache;
|
|
|
|
if (is_numeric($device)) {
|
|
$device_id = $device;
|
|
$device = device_by_id_cache($device_id);
|
|
} else {
|
|
$device_id = $device['device_id'];
|
|
}
|
|
|
|
// Set custom mibs order
|
|
$mibs_order_default = [ 'model', 'os', 'group', 'default' ];
|
|
if (empty($mibs_order)) {
|
|
// Default order: per-model mibs (if model set) -> os mibs -> os group mibs -> default mibs
|
|
$mibs_order = $mibs_order_default;
|
|
} elseif (is_string($mibs_order)) {
|
|
// Order can passed as string with comma: 'model,os,group,default'
|
|
$mibs_order = explode(',', $mibs_order);
|
|
}
|
|
|
|
// Check if custom order used, than set first from passed argument, second from default
|
|
if ($mibs_order_custom = ($mibs_order !== $mibs_order_default)) {
|
|
// Set first from passed argument, second
|
|
$mibs_order = array_unique(array_merge($mibs_order, $mibs_order_default));
|
|
}
|
|
if ($check_sysORID && !in_array('sysorid', $mibs_order, TRUE)) {
|
|
// Append discovered MIBs after model defined MIBs (of first)
|
|
if (in_array('model', $mibs_order, TRUE)) {
|
|
// [ 'model', 'sysorid', 'os', 'group', 'default' ]
|
|
$mibs_order = array_push_after($mibs_order, array_search('model', $mibs_order, TRUE), 'sysorid');
|
|
} else {
|
|
// [ 'sysorid', 'os', 'group', 'default' ]
|
|
array_unshift($mibs_order, 'sysorid');
|
|
}
|
|
}
|
|
|
|
// Do not cache MIBs if custom order used, unknown $device_id or in PHPUNIT
|
|
// When sysORID (and discovered) MIBs not requested, do not use cache!
|
|
$use_cache = $device_id && $check_sysORID && !$mibs_order_custom && !defined('__PHPUNIT_PHAR__');
|
|
|
|
// Just return cached MIBs (when exist)
|
|
if ($use_cache && isset($cache['devices']['mibs'][$device_id])) {
|
|
return $cache['devices']['mibs'][$device_id];
|
|
}
|
|
|
|
// Cache main device MIBs list
|
|
if (!$use_cache || !isset($cache['devices']['mibs'][$device_id])) {
|
|
$mibs = array();
|
|
foreach ($mibs_order as $order) {
|
|
switch ($order) {
|
|
case 'model':
|
|
$model_array = get_model_array($device);
|
|
if (is_array($model_array) && isset($model_array['mibs'])) {
|
|
$mibs = array_merge($mibs, (array)$model_array['mibs']);
|
|
print_debug_vars($model_array['mibs']);
|
|
}
|
|
break;
|
|
case 'sysorid':
|
|
// Get sysORID (and mibs discovery) supplied MIBs
|
|
$sysORID = safe_json_decode(get_entity_attrib('device', $device, 'sysORID'));
|
|
// Attach sysORID (and discovered) MIBs
|
|
if (is_array($sysORID) && !safe_empty($sysORID)) {
|
|
$mibs = array_merge($mibs, (array)$sysORID);
|
|
}
|
|
print_debug_vars($sysORID);
|
|
break;
|
|
case 'os':
|
|
$mibs = array_merge($mibs, (array)$config['os'][$device['os']]['mibs']);
|
|
break;
|
|
case 'group':
|
|
$os_group = $config['os'][$device['os']]['group'];
|
|
$mibs = array_merge($mibs, (array)$config['os_group'][$os_group]['mibs']);
|
|
break;
|
|
case 'default':
|
|
//var_dump($config['os_group']['default']['mibs']);
|
|
$mibs = array_merge($mibs, (array)$config['os_group']['default']['mibs']);
|
|
break;
|
|
}
|
|
}
|
|
$mibs = array_unique($mibs);
|
|
|
|
//$mibs = array_unique(array_merge((array)$mibs, (array)$config['os'][$device['os']]['mibs'],
|
|
// (array)$config['os_group'][$config['os'][$device['os']]['group']]['mibs'],
|
|
// (array)$config['os_group']['default']['mibs']));
|
|
|
|
// Remove blacklisted MIBs from array
|
|
//print_vars(get_device_mibs_blacklist($device));
|
|
$mibs = array_diff($mibs, get_device_mibs_blacklist($device));
|
|
|
|
if ($use_cache) {
|
|
$cache['devices']['mibs'][$device_id] = $mibs;
|
|
}
|
|
} else {
|
|
$mibs = $cache['devices']['mibs'][$device_id];
|
|
}
|
|
//print_error('$cache[\'devices\'][\'mibs\'][$device_id]');
|
|
//print_vars($cache['devices']['mibs'][$device_id]);
|
|
//print_vars($mibs);
|
|
|
|
//print_error('$mibs');
|
|
return $mibs;
|
|
}
|
|
|
|
/**
|
|
* Return array of permitted MIBs for device
|
|
*
|
|
* @param array $device
|
|
* @param mixed $mibs_order
|
|
*
|
|
* @return array All MIB permitted for device
|
|
*/
|
|
function get_device_mibs_permitted($device, $mibs_order = NULL) {
|
|
$mibs = [];
|
|
foreach (get_device_mibs($device, TRUE, $mibs_order) as $mib) {
|
|
if (is_device_mib($device, $mib)) {
|
|
$mibs[] = $mib;
|
|
}
|
|
}
|
|
|
|
return $mibs;
|
|
}
|
|
|
|
/**
|
|
* Return array with exclude MIBs for current device
|
|
*
|
|
* @param array $device Device array
|
|
* @return array Excluded MIBs
|
|
*/
|
|
function get_device_mibs_blacklist(array $device) {
|
|
global $config;
|
|
|
|
// os_group mib excludes
|
|
if (isset($config['os'][$device['os']]['group'], $config['os_group'][$config['os'][$device['os']]['group']]['mib_blacklist'])) {
|
|
$group_mibs_exclude = (array)$config['os_group'][$config['os'][$device['os']]['group']]['mib_blacklist'];
|
|
if (isset($config['os'][$device['os']]['mibs'])) {
|
|
// if mib defined for os, do not exclude it by group definitions
|
|
$group_mibs_exclude = array_diff($group_mibs_exclude, (array)$config['os'][$device['os']]['mibs']);
|
|
}
|
|
}
|
|
|
|
// os mib excludes
|
|
if (isset($config['os'][$device['os']]['mib_blacklist'])) {
|
|
$os_mibs_exclude = (array)$config['os'][$device['os']]['mib_blacklist'];
|
|
if (isset($group_mibs_exclude)) {
|
|
// append defined for os_group
|
|
return array_unique(array_merge($os_mibs_exclude, $group_mibs_exclude));
|
|
}
|
|
|
|
return $os_mibs_exclude;
|
|
}
|
|
|
|
if (isset($group_mibs_exclude)) {
|
|
return $group_mibs_exclude;
|
|
}
|
|
|
|
// no excludes defined
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Return array from DB with disabled mibs for device
|
|
*
|
|
* @param array|integer $device Device array
|
|
* @return array List of disabled MIBs for device
|
|
*/
|
|
function get_device_mibs_disabled($device) {
|
|
global $cache;
|
|
|
|
if (is_numeric($device)) {
|
|
$device_id = $device;
|
|
$device = device_by_id_cache($device_id);
|
|
} else {
|
|
$device_id = $device['device_id'];
|
|
}
|
|
|
|
// Return cached
|
|
if (isset($cache['devices']['mibs_disabled'][$device_id])) {
|
|
return $cache['devices']['mibs_disabled'][$device_id];
|
|
}
|
|
|
|
$params = [ $device['device_id'], 'mib', '1' ];
|
|
$where = "`device_id` = ? AND `use` = ? AND `disabled` = ?";
|
|
|
|
if ($disabled = dbFetchColumn("SELECT `mib` FROM `devices_mibs` WHERE $where", $params)) {
|
|
$cache['devices']['mibs_disabled'][$device_id] = $disabled;
|
|
} else {
|
|
// If none disabled, cache anyway for do not query db again
|
|
$cache['devices']['mibs_disabled'][$device_id] = [];
|
|
}
|
|
|
|
return $cache['devices']['mibs_disabled'][$device_id];
|
|
}
|
|
|
|
/**
|
|
* Set mib disabled in DB for device.
|
|
* Return IDs added or changed in DB.
|
|
*
|
|
* @param array|integer $device Device array
|
|
* @param string $mib MIB name
|
|
* @param boolean $remove Remove MIB db entry complete
|
|
* @param boolean|string $disabled TRUE for disable, FALSE for enable
|
|
*
|
|
* @return integer ID of db entry for disabled MIB
|
|
*/
|
|
function set_device_mib_disable($device, $mib, $remove = FALSE, $disabled = TRUE) {
|
|
if (safe_empty($mib)) {
|
|
// MIB name required
|
|
print_debug(__FUNCTION__ . "() required non empty mib name.");
|
|
return FALSE;
|
|
}
|
|
|
|
if (is_numeric($device)) {
|
|
$device_id = $device;
|
|
$device = device_by_id_cache($device_id);
|
|
}
|
|
|
|
// Fetch/validate if MIB in db
|
|
$mib_db = dbFetchRow("SELECT `mib_id`, `disabled` FROM `devices_mibs` WHERE `device_id` = ? AND `use` = ? AND `mib` = ?", [ $device['device_id'], 'mib', $mib ]);
|
|
|
|
// Just delete from DB if remove requested
|
|
if ($remove) {
|
|
if ($mib_db['mib_id']) {
|
|
return dbDelete('devices_mibs', '`mib_id` = ?', [$mib_db['mib_id']]);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Convert to sql boolean
|
|
$disabled = $disabled ? '1' : '0';
|
|
|
|
if (!$mib_db['mib_id']) {
|
|
// Not exist, insert
|
|
return dbInsert([ 'device_id' => $device['device_id'], 'mib' => $mib,
|
|
'use' => 'mib', 'disabled' => $disabled ], 'devices_mibs');
|
|
}
|
|
|
|
if ($mib_db['disabled'] != $disabled) {
|
|
// Exist, but changed
|
|
dbUpdate([ 'disabled' => $disabled ], 'devices_mibs', '`mib_id` = ?', [ $mib_db['mib_id'] ]);
|
|
}
|
|
|
|
return $mib_db['mib_id'];
|
|
}
|
|
|
|
/**
|
|
* Set mib enabled in DB for device.
|
|
* Return IDs added or changed in DB.
|
|
*
|
|
* @param array $device Device array
|
|
* @param string $mib MIB name
|
|
* @param boolean $remove Remove MIB db entry complete
|
|
* @param boolean $disabled TRUE for disable, FALSE for enable
|
|
*
|
|
* @return integer ID of db entry for disabled MIB
|
|
*/
|
|
function set_device_mib_enable($device, $mib, $remove = FALSE, $disabled = FALSE)
|
|
{
|
|
// Call to disable, just with different default
|
|
return set_device_mib_disable($device, $mib, $remove, $disabled);
|
|
}
|
|
|
|
/**
|
|
* Return array from DB with disabled Objects for device and specified MIB name
|
|
*
|
|
* @param array|integer $device Device array
|
|
* @param string $mib MIB name
|
|
*
|
|
* @return array List of disabled MIBs for device
|
|
*/
|
|
function get_device_objects_disabled($device, $mib = NULL)
|
|
{
|
|
global $cache;
|
|
|
|
if (is_numeric($device))
|
|
{
|
|
$device_id = $device;
|
|
$device = device_by_id_cache($device_id);
|
|
} else {
|
|
$device_id = $device['device_id'];
|
|
}
|
|
|
|
$params = [$device['device_id'], 'oid', '1'];
|
|
$where = "`device_id` = ? AND `use` = ? AND `disabled` = ?";
|
|
if (empty($mib))
|
|
{
|
|
// For empty mib see NULL or empty string
|
|
// This is common for numeric Oids
|
|
$where .= " AND (`mib` = '' OR `mib` IS NULL)";
|
|
$mib = '__mib'; // Just for caching
|
|
} else {
|
|
$where .= " AND `mib` = ?";
|
|
$params[] = $mib;
|
|
}
|
|
|
|
// Return cached
|
|
if (isset($cache['devices']['objects_disabled'][$device_id][$mib]))
|
|
{
|
|
return $cache['devices']['objects_disabled'][$device_id][$mib];
|
|
}
|
|
|
|
// Query db for objects
|
|
if ($disabled = dbFetchColumn("SELECT `object` FROM `devices_mibs` WHERE $where", $params))
|
|
{
|
|
$cache['devices']['objects_disabled'][$device_id][$mib] = $disabled;
|
|
} else {
|
|
// If none disabled, cache anyway for do not query db again
|
|
$cache['devices']['objects_disabled'][$device_id][$mib] = [];
|
|
}
|
|
|
|
return $cache['devices']['objects_disabled'][$device_id][$mib];
|
|
}
|
|
|
|
/**
|
|
* Set object disabled in DB for device.
|
|
* Return IDs added or changed in DB.
|
|
*
|
|
* @param array|int $device Device array
|
|
* @param string $object Object name
|
|
* @param string $mib MIB name (optional)
|
|
* @param boolean $remove Remove MIB db entry complete
|
|
* @param boolean $disabled TRUE for disable, FALSE for enable
|
|
*
|
|
* @return integer ID of db entry for disabled MIB
|
|
*/
|
|
function set_device_object_disable($device, $object, $mib = '', $remove = FALSE, $disabled = TRUE) {
|
|
if (safe_empty($object)) {
|
|
// MIB name required
|
|
print_debug(__FUNCTION__ . "() required non empty object name.");
|
|
return FALSE;
|
|
}
|
|
|
|
if (is_numeric($device)) {
|
|
$device_id = $device;
|
|
$device = device_by_id_cache($device_id);
|
|
}
|
|
|
|
// Initial insert array
|
|
$insert_array = [ 'device_id' => $device['device_id'], 'object' => $object,
|
|
'use' => 'object', 'disabled' => '1' ];
|
|
|
|
$where = '`device_id` = ? AND `use` = ? AND `object` = ?';
|
|
$params = [$device['device_id'], 'object', $object];
|
|
if (safe_empty($mib)) {
|
|
// For empty mib see NULL or empty string
|
|
// This is common for numeric Oids
|
|
$where .= " AND (`mib` = '' OR `mib` IS NULL)";
|
|
} else {
|
|
$where .= " AND `mib` = ?";
|
|
$params[] = $mib;
|
|
|
|
// Append mib to insert
|
|
$insert_array['mib'] = $mib;
|
|
}
|
|
// Fetch/validate if MIB in db
|
|
$mib_db = dbFetchRow("SELECT `mib_id`, `disabled` FROM `devices_mibs` WHERE $where", $params);
|
|
|
|
// Just delete from DB if remove requested
|
|
if ($remove) {
|
|
if ($mib_db['mib_id']) {
|
|
return dbDelete('devices_mibs', '`mib_id` = ?', [$mib_db['mib_id']]);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Convert to sql boolean
|
|
$disabled = $disabled ? '1' : '0';
|
|
|
|
if (!$mib_db['mib_id']) {
|
|
// Not exist, insert
|
|
return dbInsert($insert_array, 'devices_mibs');
|
|
}
|
|
if ($mib_db['disabled'] !== $disabled) {
|
|
// Exist, but changed
|
|
dbUpdate(array('disabled' => $disabled), 'devices_mibs', '`mib_id` = ?', array($mib_db['mib_id']));
|
|
}
|
|
|
|
return $mib_db['mib_id'];
|
|
}
|
|
|
|
/**
|
|
* Set object enabled in DB for device.
|
|
* Return IDs added or changed in DB.
|
|
*
|
|
* @param array $device Device array
|
|
* @param string $object Object name
|
|
* @param string $mib MIB name (optional)
|
|
* @param boolean $remove Remove MIB db entry complete
|
|
* @param boolean $disabled TRUE for disable, FALSE for enable
|
|
*
|
|
* @return integer ID of db entry for disabled MIB
|
|
*/
|
|
function set_device_object_enable($device, $object, $mib = '', $remove = FALSE, $disabled = FALSE)
|
|
{
|
|
// Call to disable, just with different default
|
|
return set_device_object_disable($device, $object, $mib, $remove, $disabled);
|
|
}
|
|
|
|
/* End mib functions */
|
|
|
|
// DOCME needs phpdoc block
|
|
// TESTME needs unit testing
|
|
function get_entity_by_id_cache($entity_type, $entity_id) {
|
|
global $cache;
|
|
|
|
if (is_array($cache[$entity_type][$entity_id])) {
|
|
return $cache[$entity_type][$entity_id];
|
|
}
|
|
|
|
$translate = entity_type_translate_array($entity_type);
|
|
//print_vars($translate);
|
|
|
|
switch($entity_type) {
|
|
case "bill":
|
|
if (function_exists('get_bill_by_id')) {
|
|
$entity = get_bill_by_id($entity_id);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
$sql = 'SELECT * FROM `'.$translate['table'].'`';
|
|
|
|
if (isset($translate['state_table'])) {
|
|
$sql .= ' LEFT JOIN `'.$translate['state_table'].'` USING (`'.$translate['id_field'].'`)';
|
|
}
|
|
|
|
if (isset($translate['parent_table'])) {
|
|
$sql .= ' LEFT JOIN `'.$translate['parent_table'].'` USING (`'.$translate['parent_id_field'].'`)';
|
|
}
|
|
|
|
$sql .= ' WHERE `'.$translate['table'].'`.`'.$translate['id_field'].'` = ?';
|
|
|
|
//print_r($entity_type);
|
|
//print_r($entity_id);
|
|
//print_r($translate);
|
|
//print_r($sql.PHP_EOL);
|
|
|
|
$entity = dbFetchRow($sql, [ $entity_id ]);
|
|
//print_r($entity);
|
|
//print_r(dbError());
|
|
break;
|
|
}
|
|
|
|
if (is_array($entity)) {
|
|
if (function_exists('humanize_'.$entity_type)) {
|
|
$do = 'humanize_'.$entity_type;
|
|
$do($entity);
|
|
} elseif (isset($translate['humanize_function']) && function_exists($translate['humanize_function'])) {
|
|
$do = $translate['humanize_function'];
|
|
$do($entity);
|
|
}
|
|
|
|
entity_rewrite($entity_type, $entity);
|
|
$cache[$entity_type][$entity_id] = $entity;
|
|
return $entity;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
function cache_entities_by_id($entity_type, $entity_ids) {
|
|
global $cache;
|
|
|
|
$translate = entity_type_translate_array($entity_type);
|
|
//print_vars($translate);
|
|
|
|
foreach($entity_ids as $key => $entity_id)
|
|
{
|
|
// Skip non-numeric values and already cached entities
|
|
if(!is_numeric($entity_id) || is_array($cache[$entity_type][$entity_id])) { unset($entity_ids[$key]); }
|
|
}
|
|
if(safe_count($entity_ids) == 0) { return; } // Nothing to do
|
|
|
|
switch($entity_type) {
|
|
|
|
default:
|
|
|
|
$sql = 'SELECT * FROM `'.$translate['table'].'`';
|
|
|
|
if (isset($translate['state_table'])) {
|
|
$sql .= ' LEFT JOIN `'.$translate['state_table'].'` USING (`'.$translate['id_field'].'`)';
|
|
}
|
|
|
|
if (isset($translate['parent_table'])) {
|
|
$sql .= ' LEFT JOIN `'.$translate['parent_table'].'` USING (`'.$translate['parent_id_field'].'`)';
|
|
}
|
|
//$sql .= ' WHERE `'.$translate['table'].'`.`'.$translate['id_field'].'` IN ?';
|
|
//$sql .= ' WHERE `'.$translate['table'].'`.`'.$translate['id_field'].'` IN ('.implode(',', $entity_ids).')';
|
|
|
|
$sql .= ' WHERE 1 '.generate_query_values_and($entity_ids, '`'.$translate['table'].'`.`'.$translate['id_field'].'`');
|
|
//print_r($entity_type);
|
|
//print_r($entity_ids);
|
|
//print_r($translate);
|
|
//print_r($sql.PHP_EOL);
|
|
|
|
$entities = dbFetchRows($sql);
|
|
//print_r($entities);
|
|
//print_r(dbError());
|
|
break;
|
|
}
|
|
|
|
if (is_array($entities)) {
|
|
foreach ($entities as $entity) {
|
|
if (function_exists('humanize_' . $entity_type)) {
|
|
$do = 'humanize_' . $entity_type;
|
|
$do($entity);
|
|
}
|
|
else if (isset($translate['humanize_function']) && function_exists($translate['humanize_function'])) {
|
|
$do = $translate['humanize_function'];
|
|
$do($entity);
|
|
}
|
|
|
|
entity_rewrite($entity_type, $entity);
|
|
|
|
$entity_id = $entity[$translate['id_field']];
|
|
$cache[$entity_type][$entity_id] = $entity;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* Network/ARP/MAC specific entity functions */
|
|
|
|
/**
|
|
* Fetch entity IDs by network. Supported entities: device, port, ip (ipv4, ipv6 for force specific IP version)
|
|
*
|
|
* See parse_network() for possible valid network queries.
|
|
*
|
|
* @param string $entity_type Entity type (device, port)
|
|
* @param string|array $network Valid network string (or array)
|
|
* @param string $add_where Custom where string
|
|
*
|
|
* @return false|array Array with entity specific IDs
|
|
*/
|
|
function get_entity_ids_ip_by_network($entity_type, $network, $add_where = '') {
|
|
|
|
// Recursive query for array of networks
|
|
if (is_array($network)) {
|
|
$ids = [];
|
|
foreach ($network as $entry) {
|
|
if ($entry_ids = get_entity_ids_ip_by_network($entity_type, $entry, $add_where)) {
|
|
$ids[] = $entry_ids; //array_merge($ids, $entry_ids);
|
|
}
|
|
}
|
|
|
|
return array_merge([], ...$ids);
|
|
}
|
|
|
|
// Parse for valid network string
|
|
$network_array = parse_network($network);
|
|
//print_vars($network_array);
|
|
if (!$network_array) {
|
|
// Incorrect network/address string passed
|
|
return FALSE;
|
|
}
|
|
|
|
$query = 'SELECT ';
|
|
$join = '';
|
|
$where = ' WHERE 1 ';
|
|
switch ($entity_type) {
|
|
case 'ipv4':
|
|
// Force request IPv6 address
|
|
$network_array['ip_type'] = 'ipv4';
|
|
$query .= ' `ipv4_address_id`';
|
|
break;
|
|
case 'ipv6':
|
|
// Force request IPv6 address
|
|
$network_array['ip_type'] = 'ipv6';
|
|
$query .= ' `ipv6_address_id`';
|
|
break;
|
|
case 'ip':
|
|
$query .= ($network_array['ip_version'] == 4) ? ' `ipv4_address_id`' : ' `ipv6_address_id`';
|
|
break;
|
|
|
|
case 'device':
|
|
case 'devices':
|
|
$query .= ' DISTINCT `device_id`';
|
|
break;
|
|
|
|
case 'port':
|
|
case 'ports':
|
|
$query .= ' DISTINCT `port_id`';
|
|
break;
|
|
}
|
|
|
|
$params = [];
|
|
switch ($network_array['ip_type']) {
|
|
case 'ipv4':
|
|
$query .= ' FROM `ipv4_addresses`';
|
|
if ($network_array['query_type'] === 'single') {
|
|
// Exactly IP match
|
|
//$where .= ' AND BINARY `ipv4_binary` = ?';
|
|
$where .= ' AND `ipv4_binary` = ?';
|
|
//var_dump($network_array['address_binary']);
|
|
$params[] = $network_array['address_binary'];
|
|
} elseif ($network_array['query_type'] === 'network') {
|
|
// Match IP in network
|
|
$where .= ' AND `ipv4_binary` >= ? AND `ipv4_binary` <= ?';
|
|
$params[] = $network_array['network_start_binary'];
|
|
$params[] = $network_array['network_end_binary'];
|
|
} else {
|
|
// Match IP addresses by part of string
|
|
$where .= generate_query_values_and($network_array['address'], 'ipv4_address', $network_array['query_type']);
|
|
}
|
|
break;
|
|
case 'ipv6':
|
|
$query .= ' FROM `ipv6_addresses`';
|
|
if ($network_array['query_type'] === 'single') {
|
|
// Exactly IP match
|
|
$where .= ' AND `ipv6_binary` = ?';
|
|
$params[] = $network_array['address_binary'];
|
|
} elseif ($network_array['query_type'] === 'network') {
|
|
// Match IP in network
|
|
$where .= ' AND `ipv6_binary` >= ? AND `ipv6_binary` <= ?';
|
|
$params[] = $network_array['network_start_binary'];
|
|
$params[] = $network_array['network_end_binary'];
|
|
} else {
|
|
// Match IP addresses by part of string
|
|
$where .= ' AND (' . generate_query_values_ng($network_array['address'], 'ipv6_address', $network_array['query_type']) .
|
|
' OR ' . generate_query_values_ng($network_array['address'], 'ipv6_compressed', $network_array['query_type']) . ')';
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (FALSE) {
|
|
// Ignore disabled/deleted/ignored
|
|
$where .= ' AND `device_id` NOT IN (SELECT `device_id` FROM `devices` WHERE `disabled` = "1" OR `ignore` = "1")';
|
|
$where .= ' AND `port_id` NOT IN (SELECT `port_id` FROM `ports` WHERE `deleted` = "1" OR `ignore` = "1")';
|
|
} else {
|
|
// Always ignore deleted ports
|
|
$join = ' LEFT JOIN `ports` USING (`device_id`, `port_id`) ';
|
|
// IS NULL allow to search addresses without associated port
|
|
$where .= ' AND (`ports`.`deleted` != "1" OR `ports`.`deleted` IS NULL)';
|
|
}
|
|
$query .= $join;
|
|
$where .= $add_where; // Additional query, ie limit by device_id or port_id
|
|
|
|
return dbFetchColumn($query . $where, $params);
|
|
//$ids = dbFetchColumn($query . $where, $params);
|
|
//print_vars($ids);
|
|
|
|
//return $ids;
|
|
}
|
|
|
|
// DOCME needs phpdoc block
|
|
// CLEANME
|
|
/* not used anymore
|
|
function entity_type_translate($entity_type)
|
|
{
|
|
$data = entity_type_translate_array($entity_type);
|
|
if (!is_array($data)) { return NULL; }
|
|
|
|
return array($data['table'], $data['id_field'], $data['name_field'], $data['ignore_field'], $data['entity_humanize']);
|
|
}
|
|
*/
|
|
|
|
// Returns a text name from an entity type and an id
|
|
// A little inefficient.
|
|
// DOCME needs phpdoc block
|
|
// TESTME needs unit testing
|
|
function entity_name($type, $entity)
|
|
{
|
|
global $config, $entity_cache;
|
|
|
|
if (is_numeric($entity))
|
|
{
|
|
$entity = get_entity_by_id_cache($type, $entity);
|
|
}
|
|
|
|
$translate = entity_type_translate_array($type);
|
|
|
|
$text = $entity[$translate['name_field']];
|
|
|
|
return($text);
|
|
}
|
|
|
|
// Returns a text name from an entity type and an id
|
|
// A little inefficient.
|
|
// DOCME needs phpdoc block
|
|
// TESTME needs unit testing
|
|
function entity_short_name($type, $entity)
|
|
{
|
|
global $config, $entity_cache;
|
|
|
|
if (is_numeric($entity))
|
|
{
|
|
$entity = get_entity_by_id_cache($type, $entity);
|
|
}
|
|
|
|
$translate = entity_type_translate_array($type);
|
|
|
|
$text = $entity[$translate['name_field']];
|
|
|
|
return($text);
|
|
}
|
|
|
|
// Returns a text description from an entity type and an id
|
|
// A little inefficient.
|
|
// DOCME needs phpdoc block
|
|
// TESTME needs unit testing
|
|
function entity_descr($type, $entity)
|
|
{
|
|
global $config, $entity_cache;
|
|
|
|
if (is_numeric($entity))
|
|
{
|
|
$entity = get_entity_by_id_cache($type, $entity);
|
|
}
|
|
|
|
$translate = entity_type_translate_array($type);
|
|
|
|
$text = $entity[$translate['entity_descr_field']];
|
|
|
|
return($text);
|
|
}
|
|
|
|
function entity_descr_check(&$descr, $entity_type, $entity = []) {
|
|
global $config;
|
|
|
|
if (safe_empty($descr) || is_array($descr)) {
|
|
// Ignore empty (or arrays because currently we check only descr
|
|
print_debug("Skipped by empty description: $descr ");
|
|
return TRUE;
|
|
}
|
|
// Clean description (multiple spaces to single)
|
|
$descr = trim(preg_replace('/\s{2,}/', ' ', $descr));
|
|
$limit_len = 255;
|
|
|
|
// Select entity ignore config
|
|
switch ($entity_type) {
|
|
case 'sensor':
|
|
case 'status':
|
|
$ignore_equals = $config['ignore_sensor'];
|
|
$ignore_contains = $config['ignore_sensor_string'];
|
|
$ignore_regexp = $config['ignore_sensor_regexp'];
|
|
break;
|
|
|
|
case 'counter':
|
|
$ignore_equals = $config['ignore_counter'];
|
|
$ignore_contains = $config['ignore_counter_string'];
|
|
$ignore_regexp = $config['ignore_counter_regexp'];
|
|
break;
|
|
|
|
case 'storage':
|
|
$ignore_equals = $config['ignore_mount'];
|
|
$ignore_contains = $config['ignore_mount_string'];
|
|
$ignore_regexp = $config['ignore_mount_regexp'];
|
|
$limit_len = FALSE;
|
|
break;
|
|
|
|
case 'processor':
|
|
$ignore_equals = $config['ignore_processor'];
|
|
$ignore_contains = $config['ignore_processor_string'];
|
|
$ignore_regexp = $config['ignore_processor_regexp'];
|
|
break;
|
|
|
|
case 'mempool':
|
|
$ignore_equals = $config['ignore_mempool'];
|
|
$ignore_contains = $config['ignore_mempool_string'];
|
|
$ignore_regexp = $config['ignore_mempool_regexp'];
|
|
break;
|
|
|
|
case 'toner':
|
|
case 'printersupply':
|
|
$ignore_equals = $config['ignore_toner'];
|
|
$ignore_contains = $config['ignore_toner_string'];
|
|
$ignore_regexp = $config['ignore_toner_regexp'];
|
|
break;
|
|
|
|
case 'lsp':
|
|
$ignore_equals = $config['ignore_lsp'];
|
|
$ignore_contains = $config['ignore_lsp_string'];
|
|
$ignore_regexp = $config['ignore_lsp_regexp'];
|
|
break;
|
|
|
|
default:
|
|
$ignore_equals_key = 'ignore_'.$entity_type;
|
|
$ignore_contains_key = 'ignore_'.$entity_type.'_string';
|
|
$ignore_regexp_key = 'ignore_'.$entity_type.'_regexp';
|
|
if (isset($config[$ignore_equals_key]) ||
|
|
isset($config[$ignore_contains_key]) ||
|
|
isset($config[$ignore_regexp_key])) {
|
|
// Generic entity ignore
|
|
$ignore_equals = $config[$ignore_equals_key];
|
|
$ignore_contains = $config[$ignore_contains_key];
|
|
$ignore_regexp = $config[$ignore_regexp_key];
|
|
} else {
|
|
// Unknown entity, no checks
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
foreach ((array)$ignore_equals as $bi) {
|
|
if (strcasecmp($bi, $descr) == 0) {
|
|
print_debug("Skipped by equals: $bi, $descr ");
|
|
return TRUE;
|
|
}
|
|
}
|
|
foreach ((array)$ignore_contains as $bi) {
|
|
if (stripos($descr, $bi) !== FALSE) {
|
|
print_debug("Skipped by contains: $bi, $descr ");
|
|
return TRUE;
|
|
}
|
|
}
|
|
foreach ((array)$ignore_regexp as $bi) {
|
|
if (preg_match($bi, $descr) > 0) {
|
|
print_debug("Skipped by regexp: $bi, $descr ");
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// Limit descr to 255 chars accordingly as in DB
|
|
if ($limit_len && strlen($descr) > $limit_len) {
|
|
$descr = check_extension_exists('mbstring') ? mb_substr($descr, 0, $limit_len) : substr($descr, 0, $limit_len);
|
|
print_debug("Description truncated to $limit_len chars: '$descr'");
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Generate entity description based on their type and discovery definition.
|
|
*
|
|
* @param string $entity_type Entity type
|
|
* @param array $definition Entity discovery definition entry
|
|
* @param array $descr_entry Array with possible descr strings received for example from snmpwalk, also used for tag replaces
|
|
* @param integer $count Optional entity count for current Table, when > 1 descr can use optional index or different descr
|
|
* @return string Parsed entity description
|
|
*/
|
|
function entity_descr_definition($entity_type, $definition, $descr_entry, $count = 1) {
|
|
//print_vars($definition);
|
|
//print_vars($descr_entry);
|
|
|
|
// Per index definitions
|
|
if (isset($descr_entry['index']) && isset($definition['indexes'][$descr_entry['index']]['descr'])) {
|
|
// Override with per index descr definition
|
|
$definition['descr'] = $definition['indexes'][$descr_entry['index']]['descr'];
|
|
}
|
|
|
|
// Descr contain tags, prefer tag replaces
|
|
$use_tags = isset($definition['descr']) && str_contains($definition['descr'], '%');
|
|
|
|
if (isset($definition['oid_descr']) && str_contains($definition['oid_descr'], '::')) {
|
|
list($mib, $definition['oid_descr']) = explode("::", $definition['oid_descr']);
|
|
}
|
|
$descr = '';
|
|
if (isset($definition['oid_descr'], $descr_entry[$definition['oid_descr']]) && !safe_empty($descr_entry[$definition['oid_descr']])) {
|
|
$descr = $descr_entry[$definition['oid_descr']];
|
|
if (!$use_tags) {
|
|
// not tags and oid_descr exist, just return it
|
|
if (isset($definition['descr_transform'])) {
|
|
$descr = string_transform($descr, $definition['descr_transform']);
|
|
}
|
|
return $descr;
|
|
}
|
|
|
|
// Append to array for correct replace
|
|
$descr_entry['oid_descr'] = $descr;
|
|
}
|
|
|
|
if (isset($definition['descr'])) {
|
|
// Use definition descr
|
|
$descr = $definition['descr'];
|
|
|
|
if ($use_tags) {
|
|
|
|
// Multipart index: Oid.0.1.2 -> %index0%, %index1%, %index2%
|
|
if (isset($descr_entry['index']) && preg_match('/%index\d+%/', $descr)) {
|
|
// Multipart index
|
|
foreach (explode('.', $descr_entry['index']) as $k => $k_index) {
|
|
$descr_entry['index'.$k] = $k_index; // Multipart indexes
|
|
}
|
|
}
|
|
|
|
// Replace tags %tag%
|
|
$descr = array_tag_replace($descr_entry, $descr);
|
|
} elseif ($count > 1 && isset($descr_entry['index'])) {
|
|
// For multi append index, but always prefer to USE TAGS!
|
|
$descr .= ' ' . $descr_entry['index'];
|
|
}
|
|
|
|
}
|
|
|
|
// Use Entity Defaults (not defined descr or oid_descr)
|
|
if (safe_empty($descr)) {
|
|
$translate = entity_type_translate_array($entity_type);
|
|
//print_vars($translate);
|
|
|
|
if ($count > 1 && isset($translate['name_multiple'])) {
|
|
$descr = $translate['name_multiple'];
|
|
} elseif (isset($translate['name'])) {
|
|
$descr = $translate['name'];
|
|
} else {
|
|
//$descr = 'Entity';
|
|
$descr = nicecase($entity_type);
|
|
}
|
|
|
|
if ($count > 1 && isset($descr_entry['index'])) {
|
|
// For multi append index
|
|
$descr .= ' ' . $descr_entry['index'];
|
|
}
|
|
}
|
|
|
|
// Transform/clean definition
|
|
if (isset($definition['descr_transform'])) {
|
|
$descr = string_transform($descr, $definition['descr_transform']);
|
|
}
|
|
|
|
//print_vars($descr);
|
|
|
|
return $descr;
|
|
}
|
|
|
|
/**
|
|
* Rule-based entity linking.
|
|
*
|
|
* @param $entity_type
|
|
* @param $definition
|
|
* @param $device
|
|
* @param $entity
|
|
*
|
|
* @return array
|
|
*/
|
|
function entity_measured_match_definition($device, $definition, $entity = [], $entity_type = NULL) {
|
|
// $entity_type unused currently
|
|
|
|
$options = [];
|
|
|
|
// Just append label for sorting and grouping
|
|
if (isset($definition['measured_label'])) {
|
|
$options['measured_entity_label'] = array_tag_replace($entity, $definition['measured_label']);
|
|
}
|
|
|
|
if (isset($definition['entity_match'])) {
|
|
// Just alternative definition key
|
|
$definition['measured_match'] = $definition['entity_match'];
|
|
}
|
|
if (!isset($definition['measured_match'])) {
|
|
if (isset($definition['measured']) && in_array($definition['measured'], [ 'port', 'outlet' ], TRUE)) {
|
|
// Currently for outlets
|
|
$options['measured_class'] = $definition['measured'];
|
|
}
|
|
return $options;
|
|
}
|
|
|
|
// Convert single match array to multi-array
|
|
if (isset($definition['measured_match']['match'])) {
|
|
$definition['measured_match'] = array($definition['measured_match']);
|
|
}
|
|
|
|
$measured_found = FALSE;
|
|
foreach ($definition['measured_match'] as $rule) {
|
|
// Allow tests here to allow multiple match rules on the same sensor table (entity-mib, etc)
|
|
|
|
// First we make substitutions using %key%, then we run transformations
|
|
|
|
// Switch search by LIKE or any (default is exactly match)
|
|
$sql_condition = isset($rule['condition']) && $rule['condition'] ? $rule['condition'] : NULL;
|
|
|
|
$rule['match'] = array_tag_replace($entity, $rule['match']);
|
|
|
|
if (is_array($rule['transform'])) {
|
|
$rule['match'] = string_transform($rule['match'], $rule['transform']);
|
|
}
|
|
|
|
// Associate defined entity type
|
|
//$sql_options = [ 'no_leading_and' ];
|
|
$sql_options = [];
|
|
switch($rule['entity_type']) {
|
|
case 'entity':
|
|
// Generic entities
|
|
switch(strtolower($rule['field'])) {
|
|
case 'descr':
|
|
case 'name':
|
|
case 'label':
|
|
$sql_rules = [];
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'entity_descr', $sql_condition, $sql_options);
|
|
if (!safe_empty($rule['class'])) {
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'entity_class', $sql_condition, $sql_options);
|
|
}
|
|
$sql_rule = implode(' AND ', $sql_rules);
|
|
$sql = "SELECT * FROM `entities` WHERE `device_id` = ? AND ($sql_rule) AND `deleted` = ? LIMIT 1";
|
|
$params = [ $device['device_id'], 0 ];
|
|
if ($measured = dbFetchRow($sql, $params)) {
|
|
$options['measured_class'] = 'entity';
|
|
$options['measured_entity'] = $measured['entity_id'];
|
|
$options['entPhysicalIndex_measured'] = $measured['entity_index'];
|
|
$options['measured_entity_label'] = $measured['entity_descr'];
|
|
$options['entity_label'] = $measured['entity_descr'];
|
|
print_debug('Linked to entity '.$measured['entity_id'].' via descr');
|
|
$measured_found = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 'index':
|
|
$sql_rules = [];
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'entity_index', $sql_condition, $sql_options);
|
|
if (!safe_empty($rule['class'])) {
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'entity_class', $sql_condition, $sql_options);
|
|
}
|
|
$sql_rule = implode(' AND ', $sql_rules);
|
|
$sql = "SELECT * FROM `entities` WHERE `device_id` = ? AND ($sql_rule) AND `deleted` = ? LIMIT 1";
|
|
$params = [ $device['device_id'], 0 ];
|
|
if ($measured = dbFetchRow($sql, $params)) {
|
|
$options['measured_class'] = 'entity';
|
|
$options['measured_entity'] = $measured['entity_id'];
|
|
$options['entPhysicalIndex_measured'] = $measured['entity_index'];
|
|
$options['measured_entity_label'] = $measured['entity_descr'];
|
|
$options['entity_label'] = $measured['entity_descr'];
|
|
print_debug('Linked to entity '.$measured['entity_id'].' via index');
|
|
$measured_found = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'port':
|
|
// Port entities
|
|
switch(strtolower($rule['field'])) {
|
|
case 'ifdescr':
|
|
case 'ifname':
|
|
case 'label':
|
|
$sql_rules = [];
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'ifDescr', $sql_condition, $sql_options);
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'ifName', $sql_condition, $sql_options);
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'port_label', $sql_condition, $sql_options);
|
|
$sql_rules[] = generate_query_values_ng($rule['match'], 'port_label_short', $sql_condition, $sql_options);
|
|
$sql_rule = implode(' OR ', $sql_rules);
|
|
$sql = "SELECT * FROM `ports` WHERE `device_id` = ? AND ($sql_rule) AND `deleted` = ? LIMIT 1";
|
|
$params = [ $device['device_id'], 0 ];
|
|
if ($measured = dbFetchRow($sql, $params)) {
|
|
$options['measured_class'] = 'port';
|
|
$options['measured_entity'] = $measured['port_id'];
|
|
$options['entPhysicalIndex_measured'] = $measured['ifIndex'];
|
|
$options['measured_entity_label'] = $measured['port_label'];
|
|
$options['port_label'] = $measured['port_label'];
|
|
print_debug('Linked to port '.$measured['port_id'].' via ifDescr');
|
|
$measured_found = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 'ifalias':
|
|
$sql_rule = generate_query_values_ng($rule['match'], 'ifAlias', $sql_condition, $sql_options);
|
|
$sql = "SELECT * FROM `ports` WHERE `device_id` = ? AND $sql_rule AND `deleted` = ? LIMIT 1";
|
|
$params = [ $device['device_id'], 0 ];
|
|
if ($measured = dbFetchRow($sql, $params)) {
|
|
$options['measured_class'] = 'port';
|
|
$options['measured_entity'] = $measured['port_id'];
|
|
$options['entPhysicalIndex_measured'] = $measured['ifIndex'];
|
|
$options['measured_entity_label'] = $measured['port_label'];
|
|
$options['port_label'] = $measured['port_label'];
|
|
print_debug('Linked to port '.$measured['port_id'].' via ifAlias');
|
|
$measured_found = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 'ifindex':
|
|
if ($measured = get_port_by_index_cache($device['device_id'], $rule['match'])) {
|
|
$options['measured_class'] = 'port';
|
|
$options['measured_entity'] = $measured['port_id'];
|
|
$options['entPhysicalIndex_measured'] = $measured['ifIndex'];
|
|
$options['measured_entity_label'] = $measured['port_label'];
|
|
$options['port_label'] = $measured['port_label'];
|
|
print_debug('Linked to port '.$measured['port_id'].' via ifIndex');
|
|
$measured_found = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
if ($measured_found) { break; } // Stop foreach if measured match found
|
|
}
|
|
|
|
// If passed $entity_type arg, do something
|
|
switch ($entity_type) {
|
|
case 'ip-address':
|
|
case 'ip-addresses':
|
|
// Return measured array instead options
|
|
if ($measured_found) { $options = $measured; }
|
|
break;
|
|
}
|
|
|
|
return $options;
|
|
}
|
|
|
|
function entity_scale_definition($device, $definition, $entity, $entity_type = NULL) {
|
|
|
|
if (isset($definition['oid_scale'])) {
|
|
if (isset($entity[$definition['oid_scale']])) {
|
|
// Scale in same table
|
|
$scale = $entity[$definition['oid_scale']];
|
|
if (isset($definition['map_scale'][$scale])) {
|
|
// Scale map defined, just return it (ie SUPERMICRO-HEALTH-MIB)
|
|
print_debug("Scale mapped from value [".$scale."] to ".$definition['map_scale'][$scale]);
|
|
return $definition['map_scale'][$scale];
|
|
}
|
|
if ((isset($definition['scale_si']) && $definition['scale_si']) || !is_numeric($scale)) {
|
|
// Ie for ENTITY-SENSOR-MIB scale in SI units (and not already mapped in definition)
|
|
// Also see in CISCOSB-SENSOR-MIB
|
|
// Also see in ORION-BASE-MIB
|
|
$precission = is_numeric($entity[$definition['oid_precision']]) ? $entity[$definition['oid_precision']] : NULL;
|
|
$scale = si_to_scale($scale, $precission);
|
|
print_debug("Scale converted from SI unit [".$entity[$definition['oid_scale']]."] and precision [$precission] to $scale");
|
|
}
|
|
} elseif (str_contains_array($definition['oid_scale'], '.')) {
|
|
// Scale is outside from table with single index, see SP2-MIB
|
|
$scale = snmp_cache_oid($device, $definition['oid_scale'], $definition['mib']);
|
|
// Translate scale from specific Oid
|
|
if (isset($definition['map_scale'][$scale])) {
|
|
print_debug("Scale mapped from value [".$scale."] to ".$definition['map_scale'][$scale]);
|
|
return $definition['map_scale'][$scale];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback to 1 if scale not found or not numeric
|
|
if (!is_numeric($scale)) {
|
|
$scale = 1;
|
|
if (isset($definition['scale'])) {
|
|
if (is_array($definition['scale'])) {
|
|
// See SPAGENT-MIB definition and https://jira.observium.org/browse/OBS-3836
|
|
//print_vars($definition);
|
|
//print_vars($entity);
|
|
if (isset($definition['scale']['scale'])) {
|
|
// Convert single condition to multi
|
|
$definition['scale'] = [ $definition['scale'] ];
|
|
}
|
|
foreach ($definition['scale'] as $test) {
|
|
print_debug("Test Scale by condition: ".$test['scale']);
|
|
if (isset($test['scale']) &&
|
|
!discovery_check_requires($device, [ 'test' => $test ], $entity)) {
|
|
$scale = $test['scale'];
|
|
//print_vars($scale);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
// Common numeric
|
|
$scale = $definition['scale'];
|
|
}
|
|
}
|
|
//$scale = isset($definition['scale']) ? $definition['scale'] : 1;
|
|
}
|
|
|
|
return $scale;
|
|
}
|
|
|
|
function entity_limits_definition($device, $definition, $entity, $scale = 1) {
|
|
$options = [];
|
|
|
|
// Scale limit
|
|
$limit_scale = 1;
|
|
if (isset($definition['limit_scale'])) {
|
|
if (is_array($definition['limit_scale'])) {
|
|
// See SPAGENT-MIB definition and https://jira.observium.org/browse/OBS-3836
|
|
//print_vars($definition);
|
|
//print_vars($entity);
|
|
if (isset($definition['limit_scale']['scale'])) {
|
|
// Convert single condition to multi
|
|
$definition['limit_scale'] = [ $definition['limit_scale'] ];
|
|
}
|
|
foreach ($definition['limit_scale'] as $test) {
|
|
print_debug("Test Limit Scale by condition: ".$test['scale']);
|
|
if (isset($test['scale']) &&
|
|
!discovery_check_requires($device, [ 'test' => $test ], $entity)) {
|
|
$limit_scale = $test['scale'];
|
|
//print_vars($limit_scale);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
// if limit scale equals string 'scale' copy it (for dynamic table scales)
|
|
$limit_scale = in_array($definition['limit_scale'], [ 'scale', 'copy' ]) ? $scale : $definition['limit_scale'];
|
|
}
|
|
}
|
|
|
|
// Oids in separate MIB, see: TPLINK-DDMSTATUS-MIB definition
|
|
foreach ([ 'oid_limit_warn', 'oid_limit_nominal', 'oid_limit_delta', 'oid_limit_delta_warn',
|
|
'oid_limit_low', 'oid_limit_low_warn', 'oid_limit_high', 'oid_limit_high_warn' ] as $oid_limit) {
|
|
if (isset($definition[$oid_limit]) &&
|
|
str_contains($definition[$oid_limit], '::') && !str_contains($definition[$oid_limit], '.')) {
|
|
// remove MIB part for correctly fetch entity data
|
|
list(, $definition[$oid_limit]) = explode('::', $definition[$oid_limit], 2);
|
|
}
|
|
}
|
|
|
|
// Limit Warning Tolerance (set warnings based on high/low limits)
|
|
// See TROPIC-SHELF-MIB
|
|
$limit_warn = FALSE;
|
|
if (isset($definition['oid_limit_warn'])) {
|
|
$oid_limit = 'oid_limit_warn';
|
|
if (isset($entity[$definition[$oid_limit]])) {
|
|
// Named oid, exist in table
|
|
$limit_warn = $entity[$definition[$oid_limit]];
|
|
} elseif (str_contains($definition[$oid_limit], '.')) {
|
|
// Single param oid (outside table)
|
|
$limit_warn = snmp_cache_oid($device, $definition[$oid_limit], $definition['mib']);
|
|
}
|
|
$limit_warn = snmp_fix_numeric($limit_warn, $definition['limit_unit']);
|
|
} elseif (isset($definition['limit_warn'])) {
|
|
$limit_warn = $definition['limit_warn'];
|
|
}
|
|
|
|
// Check limits oids if set
|
|
foreach ([ 'limit_low', 'limit_low_warn', 'limit_high', 'limit_high_warn' ] as $limit) {
|
|
$oid_limit = 'oid_' . $limit;
|
|
$invalid_limit = 'invalid_' . $limit;
|
|
if (isset($definition[$oid_limit])) {
|
|
// In case, when limit oids based on extra oid, ie phase/bank (see CyberPower CPS-MIB)
|
|
$definition[$oid_limit] = array_tag_replace($entity, $definition[$oid_limit]);
|
|
|
|
if (isset($entity[$definition[$oid_limit]])) {
|
|
// Named oid, exist in table
|
|
$options[$limit] = $entity[$definition[$oid_limit]];
|
|
} elseif (str_contains($definition[$oid_limit], '.')) {
|
|
// Single param oid (outside table)
|
|
$options[$limit] = snmp_cache_oid($device, $definition[$oid_limit], $definition['mib']);
|
|
} else {
|
|
continue;
|
|
}
|
|
$options[$limit] = snmp_fix_numeric($options[$limit], $definition['limit_unit']);
|
|
if (!is_numeric($options[$limit])) {
|
|
// Skip not numeric limit values
|
|
print_debug("$limit excluded by non numeric value (" . $options[$limit] . ").");
|
|
unset($options[$limit]);
|
|
continue;
|
|
} elseif ((isset($definition[$invalid_limit]) && in_array($options[$limit], (array)$definition[$invalid_limit])) || // per each limit invalidation
|
|
(isset($definition['invalid_limit']) && in_array($options[$limit], (array)$definition['invalid_limit']))) { // more global limit invalidation
|
|
print_debug("$limit excluded by value (" . $options[$limit] . ") in invalid range [" . implode(', ', (array)$definition[$invalid_limit]) . "].");
|
|
unset($options[$limit]);
|
|
continue;
|
|
}
|
|
$options[$limit] = scale_value($options[$limit], $limit_scale);
|
|
} elseif ($limit === 'limit_low_warn' && isset($options['limit_low']) && is_numeric($limit_warn)) {
|
|
// Low Warning based on tolerance
|
|
$options[$limit] = $options['limit_low'] + scale_value($limit_warn, $limit_scale);
|
|
} elseif ($limit === 'limit_high_warn' && isset($options['limit_high']) && is_numeric($limit_warn)) {
|
|
// High Warning based on tolerance
|
|
$options[$limit] = $options['limit_high'] - scale_value($limit_warn, $limit_scale);
|
|
} elseif (isset($definition[$limit]) && is_numeric($definition[$limit])) {
|
|
$options[$limit] = $definition[$limit]; // Limit from definition
|
|
}
|
|
}
|
|
|
|
// Limits based on nominal +- delta oids (see TPT-HEALTH-MIB)
|
|
if (isset($definition['oid_limit_nominal'])) {
|
|
$oid_limit = 'oid_limit_nominal';
|
|
if (isset($entity[$definition[$oid_limit]])) {
|
|
// Named oid, exist in table
|
|
$limit_nominal = $entity[$definition[$oid_limit]];
|
|
} elseif (str_contains($definition[$oid_limit], '.')) {
|
|
// Single param oid (outside table)
|
|
$limit_nominal = snmp_cache_oid($device, $definition[$oid_limit], $definition['mib']);
|
|
} else {
|
|
$limit_nominal = FALSE;
|
|
}
|
|
}
|
|
if (is_numeric($limit_nominal)) {
|
|
// Delta in percents?
|
|
$delta_perc = isset($definition['limit_delta_perc']) && $definition['limit_delta_perc'];
|
|
|
|
// Warning limits
|
|
$limit_delta_warn = FALSE;
|
|
if (isset($definition['oid_limit_delta_warn'])) {
|
|
$oid_limit = 'oid_limit_delta_warn';
|
|
if (isset($entity[$definition[$oid_limit]])) {
|
|
// Named oid, exist in table
|
|
$limit_delta_warn = $entity[$definition[$oid_limit]];
|
|
} elseif (str_contains($definition[$oid_limit], '.')) {
|
|
// Single param oid (outside table)
|
|
$limit_delta_warn = snmp_cache_oid($device, $definition[$oid_limit], $definition['mib']);
|
|
}
|
|
} elseif (isset($definition['limit_delta_warn'])) {
|
|
$limit_delta_warn = $definition['limit_delta_warn'];
|
|
}
|
|
|
|
if (is_numeric($limit_delta_warn)) {
|
|
if ($delta_perc) {
|
|
$limit_delta_warn = $limit_nominal * ($limit_delta_warn / 100);
|
|
}
|
|
|
|
$options['limit_low_warn'] = $limit_nominal - $limit_delta_warn; //$definition['limit_scale'];
|
|
$options['limit_high_warn'] = $limit_nominal + $limit_delta_warn; //$definition['limit_scale'];
|
|
$options['limit_low_warn'] = scale_value($options['limit_low_warn'], $limit_scale);
|
|
$options['limit_high_warn'] = scale_value($options['limit_high_warn'], $limit_scale);
|
|
}
|
|
|
|
// Alert limits
|
|
$limit_delta = FALSE;
|
|
if (isset($definition['oid_limit_delta'])) {
|
|
$oid_limit = 'oid_limit_delta';
|
|
if (isset($entity[$definition[$oid_limit]])) {
|
|
// Named oid, exist in table
|
|
$limit_delta = $entity[$definition[$oid_limit]];
|
|
} elseif (str_contains($definition[$oid_limit], '.')) {
|
|
$limit_delta = snmp_cache_oid($device, $definition[$oid_limit], $definition['mib']);
|
|
}
|
|
} elseif (isset($definition['limit_delta'])) {
|
|
$limit_delta = $definition['limit_delta'];
|
|
}
|
|
|
|
if (is_numeric($limit_delta)) {
|
|
if ($delta_perc) {
|
|
$limit_delta = $limit_nominal * ($limit_delta / 100);
|
|
}
|
|
|
|
$options['limit_low'] = $limit_nominal - $limit_delta; //$definition['limit_scale'];
|
|
$options['limit_high'] = $limit_nominal + $limit_delta; //$definition['limit_scale'];
|
|
$options['limit_low'] = scale_value($options['limit_low'], $limit_scale);
|
|
$options['limit_high'] = scale_value($options['limit_high'], $limit_scale);
|
|
}
|
|
}
|
|
|
|
// One last step for convert limit unit, when value and limits use different units (ie HP-ICF-TRANSCEIVER-MIB)
|
|
if (isset($definition['limit_unit'])) {
|
|
foreach (array('limit_low', 'limit_low_warn', 'limit_high_warn', 'limit_high') as $limit) {
|
|
if (isset($options[$limit])) {
|
|
$options[$limit] = value_to_si($options[$limit], $definition['limit_unit'], $definition['class']);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Allow disable auto limits by definitions
|
|
if (isset($definition['limit_auto'])) {
|
|
$options['limit_auto'] = $definition['limit_auto'];
|
|
}
|
|
|
|
// Limit by (ie for counters)
|
|
if (isset($definition['limit_by'])) {
|
|
$options['limit_by'] = $definition['limit_by'];
|
|
}
|
|
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Translate an entity type to the relevant table and the identifier field name
|
|
*
|
|
* @param string entity_type
|
|
* @return string entity_table
|
|
* @return array entity_id
|
|
*/
|
|
// TESTME needs unit testing
|
|
function entity_type_translate_array($entity_type)
|
|
{
|
|
$translate = $GLOBALS['config']['entities'][$entity_type];
|
|
|
|
//print_r($GLOBALS['config']['entities']);
|
|
|
|
// Base fields
|
|
// FIXME, not listed here: agg_graphs, metric_graphs
|
|
$fields = array('name', // Base entity name
|
|
'name_multiple', // (Optional) Plural entity name
|
|
'table', // Table name
|
|
'table_fields', // Array with table fields
|
|
//'state_table', // State table name (deprecated)
|
|
//'state_fields', // Array with state fields (deprecated)
|
|
'humanize_function', // Humanize function name
|
|
'parent_type', // Parent table type
|
|
'parent_table', // Parent table name
|
|
'parent_id_field', // Main parent id field
|
|
'where',
|
|
'icon', // Entity icon
|
|
'graph');
|
|
foreach ($fields as $field)
|
|
{
|
|
if (isset($translate[$field]))
|
|
{
|
|
$data[$field] = $translate[$field];
|
|
}
|
|
else if (isset($GLOBALS['config']['entities']['default'][$field]))
|
|
{
|
|
$data[$field] = $GLOBALS['config']['entities']['default'][$field];
|
|
}
|
|
}
|
|
|
|
// Table fields
|
|
$fields_table = array(// Common fields
|
|
'id',
|
|
'device_id',
|
|
'index',
|
|
'mib',
|
|
'object',
|
|
'oid',
|
|
'name',
|
|
'shortname',
|
|
'descr',
|
|
'ignore',
|
|
'disable',
|
|
'deleted',
|
|
// Limits fields
|
|
'limit_high', // High critical limit
|
|
'limit_high_warn', // High warning limit
|
|
'limit_low', // Low critical limit
|
|
'limit_low_warn', // Low warning limit
|
|
// Value fields
|
|
'value', // RAW value
|
|
'status', // Entity specific status name (
|
|
'event', // Event name (ok, alert, warning, etc..)
|
|
'uptime', // Uptime
|
|
'last_change', // Last changed time
|
|
// Measured entity fields
|
|
'measured_type', // Measured entity type
|
|
'measured_id', // Measured entity id
|
|
);
|
|
if (isset($translate['table_fields']))
|
|
{
|
|
// New definition style
|
|
foreach ($translate['table_fields'] as $field => $entry)
|
|
{
|
|
// Add old style name (ie 'id_field') for compatibility
|
|
$data[$field . '_field'] = $entry;
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Returns TRUE if the logged in user is permitted to view the supplied entity.
|
|
*
|
|
* @param string|integer $entity_id
|
|
* @param string $entity_type
|
|
* @param string|mixed $device_id
|
|
* @param array $permissions Permissions array, by default used global var $permissions generated by permissions_cache()
|
|
*
|
|
* @return bool
|
|
*/
|
|
function is_entity_permitted($entity_id, $entity_type, $device_id = NULL, $permissions = NULL) {
|
|
|
|
if (is_null($permissions) && isset($GLOBALS['permissions'])) {
|
|
// Note, pass permissions array by param used in permissions_cache()
|
|
$permissions = (array)$GLOBALS['permissions'];
|
|
}
|
|
|
|
if (!is_numeric($device_id)) { $device_id = get_device_id_by_entity_id($entity_id, $entity_type); }
|
|
|
|
if ($_SESSION['userlevel'] >= 5) {
|
|
// User not limited (userlevel >= 5)
|
|
$allowed = TRUE;
|
|
} elseif (is_numeric($device_id) && device_permitted($device_id)) {
|
|
$allowed = TRUE;
|
|
} elseif (isset($permissions[$entity_type][$entity_id]) && $permissions[$entity_type][$entity_id]) {
|
|
$allowed = TRUE;
|
|
} elseif (isset($GLOBALS['auth']) && is_graph()) {
|
|
$allowed = $GLOBALS['auth'];
|
|
} else {
|
|
$allowed = FALSE;
|
|
}
|
|
|
|
if (OBS_DEBUG) {
|
|
$debug_msg = "PERMISSIONS CHECK. Entity type: $entity_type, Entity ID: $entity_id, Device ID: ".($device_id ?: 'NULL') . ", Allowed: " . ($allowed ? 'TRUE' : 'FALSE') . ".";
|
|
if (isset($GLOBALS['notifications'])) {
|
|
$GLOBALS['notifications'][] = array('text' => $debug_msg, 'severity' => 'debug');
|
|
} else {
|
|
print_debug($debug_msg);
|
|
}
|
|
}
|
|
return $allowed;
|
|
}
|
|
|
|
/**
|
|
* Returns TRUE if the logged in user is permitted to view the supplied entity.
|
|
*
|
|
* @param string|integer $entity_id
|
|
* @param string $entity_type
|
|
* @param string|mixed $device_id
|
|
* @param array $permissions Permissions array, by default used global var $permissions generated by permissions_cache()
|
|
*
|
|
* @return bool
|
|
*/
|
|
function is_entity_write_permitted($entity_id, $entity_type, $device_id = NULL, $permissions = NULL) {
|
|
|
|
if (is_null($permissions) && isset($GLOBALS['permissions'])) {
|
|
// Note, pass permissions array by param used in permissions_cache()
|
|
$permissions = (array)$GLOBALS['permissions'];
|
|
}
|
|
|
|
if (!is_numeric($device_id)) { $device_id = get_device_id_by_entity_id($entity_id, $entity_type); }
|
|
|
|
if ($_SESSION['userlevel'] >= 9) {
|
|
// User has global device/entity write permissions
|
|
$allowed = TRUE;
|
|
} elseif (is_numeric($device_id) && isset($permissions['device'][$device_id]) && $permissions['device'][$device_id] === "rw") {
|
|
// User has device write permissions
|
|
$allowed = TRUE;
|
|
} elseif (isset($permissions[$entity_type][$entity_id]) && $permissions[$entity_type][$entity_id] === "rw") {
|
|
$allowed = TRUE;
|
|
} else {
|
|
$allowed = FALSE;
|
|
}
|
|
|
|
if (OBS_DEBUG) {
|
|
$debug_msg = "WRITE PERMISSIONS CHECK. Entity type: $entity_type, Entity ID: $entity_id, Device ID: ".($device_id ?: 'NULL') . ", Allowed: " . ($allowed ? 'TRUE' : 'FALSE') . ".";
|
|
if (isset($GLOBALS['notifications'])) {
|
|
$GLOBALS['notifications'][] = array('text' => $debug_msg, 'severity' => 'debug');
|
|
} else {
|
|
print_debug($debug_msg);
|
|
}
|
|
}
|
|
return $allowed;
|
|
}
|
|
|
|
/**
|
|
* Generates standardised set of array fields for use in entity-generic functions and code.
|
|
* Has no return value, it modifies the $entity array in-place.
|
|
*
|
|
* @param $entity_type string
|
|
* @param $entity array
|
|
*
|
|
*/
|
|
// TESTME needs unit testing
|
|
function entity_rewrite($entity_type, &$entity) {
|
|
$translate = entity_type_translate_array($entity_type);
|
|
|
|
// By default, fill $entity['entity_name'] with name_field contents.
|
|
if (isset($translate['name_field'])) { $entity['entity_name'] = $entity[$translate['name_field']]; }
|
|
|
|
// By default, fill $entity['entity_shortname'] with shortname_field contents. Fallback to entity_name when field name is not set.
|
|
if (isset($translate['shortname_field'])) {
|
|
$entity['entity_shortname'] = $entity[$translate['name_field']];
|
|
} else {
|
|
$entity['entity_shortname'] = $entity['entity_name'];
|
|
}
|
|
|
|
// By default, fill $entity['entity_descr'] with descr_field contents.
|
|
if (isset($translate['descr_field'])) { $entity['entity_descr'] = $entity[$translate['descr_field']]; }
|
|
|
|
// By default, fill $entity['entity_id'] with id_field contents.
|
|
if (isset($translate['id_field'])) { $entity['entity_id'] = $entity[$translate['id_field']]; }
|
|
|
|
switch($entity_type) {
|
|
case "bgp_peer":
|
|
case "bgp_peer_af":
|
|
// Special handling of name/shortname/descr for bgp_peer, since it combines multiple elements.
|
|
|
|
$addr = ip_compress($entity['bgpPeerRemoteAddr']);
|
|
|
|
$entity['entity_name'] = "AS".$entity['bgpPeerRemoteAs'] ." ". $addr;
|
|
$entity['entity_shortname'] = $addr;
|
|
$entity['entity_descr'] = $entity['astext'];
|
|
|
|
// Special code for BGP Peer AFI/SAFI
|
|
if ($entity_type === "bgp_peer_af") {
|
|
$entity['entity_name'] .= " " . $entity['afi']."/".$entity['safi'];
|
|
$entity['entity_shortname'] .= " " . $entity['afi']."/".$entity['safi'];
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case "sla":
|
|
/* moved to humanize_sla()
|
|
$entity['entity_name'] = 'SLA #' . $entity['sla_index'];
|
|
if (!empty($entity['sla_target']) && ($entity['sla_target'] != $entity['sla_tag']))
|
|
{
|
|
if (get_ip_version($entity['sla_target']) === 6)
|
|
{
|
|
$sla_target = Net_IPv6::compress($entity['sla_target'], TRUE);
|
|
} else {
|
|
$sla_target = $entity['sla_target'];
|
|
}
|
|
$entity['entity_name'] .= ' (' . $entity['sla_tag'] . ': ' . $sla_target . ')';
|
|
} else {
|
|
$entity['entity_name'] .= ' (' . $entity['sla_tag'] . ')';
|
|
}
|
|
*/
|
|
$entity['entity_name'] = $entity['sla_descr'];
|
|
$entity['entity_shortname'] = "#". $entity['sla_index'] . " (". $entity['sla_tag'] . ")";
|
|
break;
|
|
|
|
case "pseudowire":
|
|
$entity['entity_name'] = $entity['pwID'] . ($entity['pwDescr'] ? " (". $entity['pwDescr'] . ")" : '');
|
|
$entity['entity_shortname'] = $entity['pwID'];
|
|
break;
|
|
|
|
case 'probe':
|
|
if (strlen($entity['entity_descr'])) {
|
|
$entity['entity_name'] .= ' (' . $entity['entity_descr'] . ')';
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates a URL to reach the entity's page (or the most specific list page the entity appears on)
|
|
* Has no return value, it modifies the $entity array in-place.
|
|
*
|
|
* @param $entity_type string
|
|
* @param $entity array|integer
|
|
* @param $text string|null
|
|
*
|
|
*/
|
|
// TESTME needs unit testing
|
|
function generate_entity_link($entity_type, $entity, $text = NULL, $graph_type = NULL, $escape = TRUE, $options = FALSE) {
|
|
if (is_numeric($entity)) {
|
|
$entity = get_entity_by_id_cache($entity_type, $entity);
|
|
}
|
|
// Compat with old boolean $short option
|
|
if (is_array($options)) {
|
|
$short = isset($options['short']) && $options['short'];
|
|
$icon = isset($options['icon']) && $options['icon'];
|
|
$url_only = isset($options['url']) && $options['url'];
|
|
} else {
|
|
$short = $options;
|
|
$icon = FALSE;
|
|
$url_only = FALSE;
|
|
$options = [];
|
|
}
|
|
if ($icon) {
|
|
// Get entity icon and force do not escape
|
|
$text = get_icon($GLOBALS['config']['entities'][$entity_type]['icon']);
|
|
$escape = FALSE;
|
|
}
|
|
|
|
entity_rewrite($entity_type, $entity);
|
|
|
|
switch($entity_type) {
|
|
case "device":
|
|
if ($icon) {
|
|
$link = generate_device_link($entity, $text, [], FALSE);
|
|
} elseif ($url_only) {
|
|
return generate_device_url($entity);
|
|
} else {
|
|
// Not sure, forced short as previous
|
|
$link = generate_device_link_short($entity, [], 16);
|
|
}
|
|
break;
|
|
case "mempool":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'health', 'metric' => 'mempool'));
|
|
break;
|
|
case "processor":
|
|
//r($entity);
|
|
if (isset($entity['id']) && is_array($entity['id']))
|
|
{
|
|
// Multi-processors list
|
|
$ids = implode(',', $entity['id']);
|
|
$entity['entity_id'] = $ids;
|
|
} else {
|
|
$ids = $entity['processor_id'];
|
|
}
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'health', 'metric' => 'processor', 'processor_id' => $ids));
|
|
break;
|
|
case "status":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'health', 'metric' => 'status', 'id' => $entity['status_id']));
|
|
break;
|
|
case "sensor":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'health', 'metric' => $entity['sensor_class'], 'id' => $entity['sensor_id']));
|
|
break;
|
|
case "counter":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'health', 'metric' => 'counter', 'id' => $entity['counter_id']));
|
|
break;
|
|
case "printersupply":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'printing', 'supply' => $entity['supply_type']));
|
|
break;
|
|
case "port":
|
|
if ($icon) {
|
|
$link = generate_port_link($entity, $text, $graph_type, FALSE, FALSE);
|
|
} elseif ($url_only) {
|
|
return generate_port_url($entity);
|
|
} else {
|
|
//$link = generate_port_link($entity, NULL, $graph_type, $escape, $short);
|
|
$link = generate_port_link($entity, $text, $graph_type, $escape, $short);
|
|
}
|
|
break;
|
|
case "storage":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'health', 'metric' => 'storage'));
|
|
break;
|
|
case "bgp_peer":
|
|
case "bgp_peer_af":
|
|
$url = generate_url(array('page' => 'device', 'device' => ($entity['peer_device_id'] ? $entity['peer_device_id'] : $entity['device_id']), 'tab' => 'routing', 'proto' => 'bgp'));
|
|
break;
|
|
case "netscalervsvr":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'loadbalancer', 'type' => 'netscaler_vsvr', 'vsvr' => $entity['vsvr_id']));
|
|
break;
|
|
case "netscalersvc":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'loadbalancer', 'type' => 'netscaler_services', 'svc' => $entity['svc_id']));
|
|
break;
|
|
case "netscalersvcgrpmem":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'loadbalancer', 'type' => 'netscaler_servicegroupmembers', 'svc' => $entity['svc_id']));
|
|
break;
|
|
case "p2pradio":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'p2pradios'));
|
|
break;
|
|
case "sla":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'slas', 'id' => $entity['sla_id']));
|
|
break;
|
|
case "pseudowire":
|
|
$url = generate_url(array('page' => 'device', 'device' => $entity['device_id'], 'tab' => 'pseudowires', 'id' => $entity['pseudowire_id']));
|
|
break;
|
|
case "maintenance":
|
|
$url = generate_url(array('page' => 'alert_maintenance', 'maintenance' => $entity['maint_id']));
|
|
break;
|
|
case "group":
|
|
$url = generate_url(array('page' => 'group', 'group_id' => $entity['group_id']));
|
|
break;
|
|
case "virtualmachine":
|
|
// If we know this device by its vm name in our system, create a link to it, else just print the name.
|
|
if (get_device_id_by_hostname($entity['vm_name']))
|
|
{
|
|
if ($url_only)
|
|
{
|
|
return generate_device_url(device_by_name($entity['vm_name']));
|
|
}
|
|
$link = generate_device_link(device_by_name($entity['vm_name']));
|
|
} else {
|
|
// Hardcode $link to just show the name, no actual link
|
|
$link = $entity['vm_name'];
|
|
}
|
|
break;
|
|
case 'probe':
|
|
$url = generate_url([ 'page' => 'device', 'device' => $entity['device_id'], 'tab' => 'probes' ]);
|
|
break;
|
|
default:
|
|
$url = NULL;
|
|
}
|
|
|
|
if ($url_only) {
|
|
return $url;
|
|
}
|
|
if (isset($link)) {
|
|
return $link;
|
|
}
|
|
|
|
if (!isset($text))
|
|
{
|
|
if ($short && $entity['entity_shortname'])
|
|
{
|
|
$text = $entity['entity_shortname'];
|
|
} else {
|
|
$text = $entity['entity_name'];
|
|
}
|
|
}
|
|
if ($escape) { $text = escape_html($text); }
|
|
$link = '<a href="' . $url . '" class="entity-popup ' . $entity['html_class'] . '" data-eid="' . $entity['entity_id'] . '" data-etype="' . $entity_type . '">' . $text . '</a>';
|
|
|
|
return $link;
|
|
}
|
|
|
|
/**
|
|
* This function generate link to entity, but without any text descriptions
|
|
*
|
|
* @param $entity_type
|
|
* @param $entity
|
|
*
|
|
* @return string
|
|
*/
|
|
function generate_entity_icon_link($entity_type, $entity)
|
|
{
|
|
return generate_entity_link($entity_type, $entity, NULL, NULL, FALSE, ['icon' => TRUE]);
|
|
}
|
|
|
|
/**
|
|
* This function generate url to entity
|
|
*
|
|
* @param $entity_type
|
|
* @param $entity
|
|
*
|
|
* @return string
|
|
*/
|
|
function generate_entity_url($entity_type, $entity)
|
|
{
|
|
return generate_entity_link($entity_type, $entity, NULL, NULL, FALSE, ['url' => TRUE]);
|
|
}
|
|
|
|
/**
|
|
* Fetch rrd filename for specified Entity ID
|
|
*
|
|
* @param string $entity_type Entity type
|
|
* @param integer $entity_id Entity ID
|
|
*
|
|
* @return string RRD filename
|
|
*/
|
|
function get_entity_rrd_by_id($entity_type, $entity_id)
|
|
{
|
|
$entity = get_entity_by_id_cache($entity_type, $entity_id);
|
|
$device = device_by_id_cache($entity['device_id']);
|
|
|
|
switch ($entity_type)
|
|
{
|
|
case 'sensor':
|
|
$filename = get_sensor_rrd($device, $entity);
|
|
break;
|
|
case 'status':
|
|
$filename = get_status_rrd($device, $entity);
|
|
break;
|
|
case 'counter':
|
|
$filename = get_counter_rrd($device, $entity);
|
|
break;
|
|
}
|
|
|
|
return $filename;
|
|
}
|
|
|
|
// EOF
|