You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

411 lines
11 KiB

1 year ago
<?php
/*
** Zabbix
** Copyright (C) 2001-2023 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
require_once 'vendor/autoload.php';
require_once dirname(__FILE__).'/../../../include/defines.inc.php';
require_once dirname(__FILE__).'/../../../include/hosts.inc.php';
require_once dirname(__FILE__).'/../../../include/db.inc.php';
class CDataHelper extends CAPIHelper {
protected static $data = null;
protected static $request = [];
protected static $response = [];
/**
* Prepare request for API call and make API call (@see callRaw).
*
* @param string $method API method to be called.
* @param mixed $params API call params.
*
* @return array
*
* @throws Exception on API error
*/
public static function call($method, $params) {
global $URL;
if (!$URL) {
$URL = PHPUNIT_URL.'api_jsonrpc.php';
}
static::$request = [];
static::$response = [];
if (CAPIHelper::getSessionId() === null) {
CAPIHelper::createSessionId();
}
$response = CAPIHelper::call($method, $params);
if (array_key_exists('error', $response)) {
throw new Exception('API call failed: '.json_encode($response['error'], JSON_PRETTY_PRINT));
}
if (!array_key_exists('result', $response)) {
throw new Exception('API call failed: result is not present');
}
static::$request = (CTestArrayHelper::isAssociative($params)) ? [$params] : $params;
static::$response = $response['result'];
return static::$response;
}
/**
* Prepare request for API call and make API call (@see callRaw).
*
* @param string $method API method to be called.
* @param mixed $params API call params.
*
* @return array
*
* @throws Exception on API error
*/
public static function getIds($field) {
$ids = [];
$result = reset(static::$response);
if (count(static::$request) !== count($result)) {
throw new Exception('Failed to get ids: record counts don\'t match');
}
foreach (static::$request as $i => $object) {
if (!array_key_exists($field, $object)) {
throw new Exception('Failed to get ids: field "'.$field.'" is not present in request.');
}
if (!array_key_exists($i, $result)) {
throw new Exception('Failed to get ids: element ('.$i.') is not present in result.');
}
if (array_key_exists($object[$field], $ids)) {
throw new Exception('Failed to get ids: field "'.$field.'" is not unique.');
}
$ids[$object[$field]] = $result[$i];
}
return $ids;
}
/**
* Create host with items and discovery rules.
*
* @param mixed $params API call params.
* In addition to the default host.create params, "items" and "discoveryrules" can be set
* for any of the host in order to create host items and discovery rules.
*
* @return array
*/
public static function createHosts($params) {
return static::createHostTemplate($params, 'host');
}
/**
* Create template with items and discovery rules.
*
* @param mixed $params API call params
*
* @return array
*/
public static function createTemplates($params) {
return static::createHostTemplate($params, 'template');
}
/**
* Execute creation of host or template.
*
* @param mixed $params API call params
* @param string $object host or template object
*
* @return array
*/
public static function createHostTemplate($params, $object) {
$items = [];
$discoveryrules = [];
foreach ($params as &$param) {
if (array_key_exists('items', $param)) {
$items[$param['host']] = $param['items'];
unset($param['items']);
}
if (array_key_exists('discoveryrules', $param)) {
$discoveryrules[$param['host']] = $param['discoveryrules'];
unset($param['discoveryrules']);
}
}
unset($param);
static::call($object.'.create', $params);
$objectids = static::getIds('host');
$result = [
$object.'ids' => $objectids
];
if ($items) {
$result['itemids'] = static::createItems('item', $items, $objectids, $object);
}
if ($discoveryrules) {
$result['discoveryruleids'] = static::createItems('discoveryrule', $discoveryrules, $objectids, $object);
}
return $result;
}
/**
* Get host interfaces.
*
* @param array $hostids host ids
*
* @return array
*/
public static function getInterfaces($hostids) {
$hosts = static::call('host.get', [
'output' => ['host'],
'hostids' => array_values($hostids),
'selectInterfaces' => ['interfaceid', 'useip', 'ip', 'type', 'dns', 'port', 'main']
]);
$result['default_interfaces'] = [];
$result['ids'] = [];
foreach ($hosts as $host) {
foreach ($host['interfaces'] as $interface) {
if ($interface['main'] == INTERFACE_PRIMARY) {
$result['default_interfaces'][$host['host']][$interface['type']] = $interface['interfaceid'];
}
$address = ($interface['useip'] == 1) ? $interface['ip'] : $interface['dns'];
$result['ids'][$host['host']][$address.':'.$interface['port']] = $interface['interfaceid'];
}
}
return $result;
}
/**
* Create items or discovery rule for host and template.
*
* @param string $type item or discoveryrule type
* @param mixed $items API call items or discovery params
* @param array $objectids host or template ids
* @param string $object host or template
*
* @return array
*
* @throws Exception on API error
*/
public static function createItems($type, $items, $objectids, $object = 'host') {
$request = [];
foreach ($items as $host => $host_items) {
foreach ($host_items as $item) {
$item['hostid'] = $objectids[$host];
if ($object === 'host') {
$interfaces = static::getInterfaces($objectids);
if (array_key_exists($host, $interfaces['default_interfaces'])) {
$interface_type = null;
switch (CTestArrayHelper::get($item, 'type')) {
case ITEM_TYPE_ZABBIX_ACTIVE:
$interface_type = 0;
break;
case ITEM_TYPE_ZABBIX:
$interface_type = 1;
break;
case ITEM_TYPE_SNMP:
case ITEM_TYPE_SNMPTRAP:
$interface_type = 2;
break;
case ITEM_TYPE_IPMI:
$interface_type = 3;
break;
case ITEM_TYPE_JMX:
$interface_type = 4;
break;
}
if ($interface_type !== null && array_key_exists($interface_type, $interfaces['default_interfaces'][$host])) {
$item['interfaceid'] = $interfaces['default_interfaces'][$host][$interface_type];
}
}
if (array_key_exists($host, $interfaces['ids'])) {
$interface = CTestArrayHelper::get($item, 'interface');
unset($item['interface']);
if ($interface !== null && array_key_exists($$interfaces['ids'][$host], $interface)) {
$item['interfaceid'] = $interfaces['ids'][$host][$interface];
}
}
}
$request[] = $item;
}
}
// Create items or discovery rules.
$response = static::call($type.'.create', $request);
$i = 0;
$result = [];
foreach ($items as $host => $host_items) {
foreach ($host_items as $item) {
if (!array_key_exists($i, $response['itemids'])) {
throw new Exception('Failed to get ids: element ('.$i.') is not present in result.');
}
$result[$host.':'.$item['key_']] = $response['itemids'][$i++];
}
}
return $result;
}
/**
* Load the data source data from the file cache.
*/
protected static function preload() {
if (static::$data === null) {
static::$data = [];
if (!defined('PHPUNIT_DATA_DIR')) {
return;
}
foreach (new DirectoryIterator(PHPUNIT_DATA_DIR) as $file) {
if ($file->isDot() || $file->isDir() || strtolower($file->getExtension()) !== 'json') {
continue;
}
$name = $file->getBasename('.'.$file->getExtension());
static::$data[$name] = json_decode(file_get_contents($file->getPathname()), true);
}
}
}
/**
* Get data from the data sources.
*
* @param mixed $path data path to look for
* @param mixed $default default value to be returned if data doesn't exist
*
* @return mixed
*/
public static function get($path, $default = null) {
return CTestArrayHelper::get(static::$data, $path, $default);
}
/**
* Load specific data source data.
*
* @param mixed $source name of the data source(s)
*
* @return boolean
*
* @throws \Exception
*/
public static function load($source) {
if (is_array($source)) {
$result = true;
foreach ($source as $name) {
if (!static::load($name)) {
$result = false;
}
}
return $result;
}
static::preload();
if (array_key_exists($source, static::$data)) {
return true;
}
try {
$path = PHPUNIT_DATA_SOURCES_DIR.$source.'.php';
if (!file_exists($path)) {
throw new \Exception('File "'.$path.'" doesn\'t exist.');
}
require_once $path;
static::$data[$source] = forward_static_call([$source, 'load']);
if (defined('PHPUNIT_DATA_DIR')) {
$data = json_encode(static::get($source));
file_put_contents(PHPUNIT_DATA_DIR.$source.'.json', $data);
}
}
catch (\Exception $e) {
echo 'Failed to load data from data source "'.$source.'".'."\n\n".$e->getMessage()."\n".$e->getTraceAsString();
return false;
}
return true;
}
/**
* Add data to item.
*
* @param string $itemid item id
* @param array $values value that should be sent to item
* @param mixed $time time when value was received
*/
public static function addItemData($itemid, $values, $time = null) {
if (!is_array($values)) {
$values = [$values];
}
if ($time === null) {
$time = time();
}
elseif (is_array($time)) {
if (count($time) !== count($values)) {
throw new Exception('Value count should match the time record count.');
}
$time = array_values($time);
}
// Check item value type to set correct history table where to insert data.
$value_type = CDBHelper::getValue('SELECT value_type FROM items where itemid='.zbx_dbstr($itemid));
$suffixes = ['', '_str', '_log', '_uint', '_text'];
if (!array_key_exists($value_type, $suffixes)) {
throw new Exception('Unsupported item value type: '.$value_type);
}
$history_table = 'history'.$suffixes[$value_type];
foreach (array_values($values) as $key => $value) {
$clock = is_array($time) ? $time[$key] : $time;
DBexecute('INSERT INTO '.$history_table.' (itemid, clock, value) VALUES ('.zbx_dbstr($itemid).', '
.zbx_dbstr($clock).', '.zbx_dbstr($value).')');
}
}
}