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.

430 lines
12 KiB

<?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 dirname(__FILE__).'/../include/CIntegrationTest.php';
require_once dirname(__FILE__).'/../include/helpers/CDataHelper.php';
/**
* Test suite for data collection using both active and passive agents.
*
* @backup history, hosts, host_rtdata, proxy, proxy_rtdata, changelog, config, config_autoreg_tls, expressions
* @backup globalmacro, hosts, interface, item_rtdata, items, proxy_history, regexps, ha_node
*/
class testDataCollection extends CIntegrationTest {
private static $hostids = [];
private static $itemids = [];
/**
* @inheritdoc
*/
public function prepareData() {
// Create proxy "proxy".
CDataHelper::call('proxy.create', [
'name' => 'proxy',
'operating_mode' => PROXY_OPERATING_MODE_ACTIVE
]);
$proxyids = CDataHelper::getIds('name');
// Create host "agent", "custom_agent" and "proxy agent".
$interfaces = [
'type' => 1,
'main' => 1,
'useip' => 1,
'ip' => '127.0.0.1',
'dns' => '',
'port' => $this->getConfigurationValue(self::COMPONENT_AGENT, 'ListenPort')
];
$groups = ['groupid' => 4];
$result = CDataHelper::createHosts([
[
'host' => 'agent',
'interfaces' => $interfaces,
'groups' => $groups,
'status' => HOST_STATUS_NOT_MONITORED,
'items' => [
[
'name' => 'Agent ping',
'key_' => 'agent.ping',
'type' => ITEM_TYPE_ZABBIX_ACTIVE,
'value_type' => ITEM_VALUE_TYPE_UINT64,
'delay' => '1s'
],
[
'name' => 'Agent hostname',
'key_' => 'agent.hostname',
'type' => ITEM_TYPE_ZABBIX,
'value_type' => ITEM_VALUE_TYPE_TEXT,
'delay' => '1s'
]
]
],
[
'host' => 'custom_agent',
'interfaces' => $interfaces,
'groups' => $groups,
'status' => HOST_STATUS_NOT_MONITORED,
'items' => [
[
'name' => 'Custom metric 1',
'key_' => 'custom.metric',
'type' => ITEM_TYPE_ZABBIX_ACTIVE,
'value_type' => ITEM_VALUE_TYPE_TEXT,
'delay' => '5s'
],
[
'name' => 'Custom metric 2',
'key_' => 'custom.metric[custom]',
'type' => ITEM_TYPE_ZABBIX_ACTIVE,
'value_type' => ITEM_VALUE_TYPE_TEXT,
'delay' => '10s'
]
]
],
[
'host' => 'proxy_agent',
'interfaces' => $interfaces,
'groups' => $groups,
'proxyid' => $proxyids['proxy'],
'status' => HOST_STATUS_NOT_MONITORED,
'items' => [
[
'name' => 'Agent ping',
'key_' => 'agent.ping',
'type' => ITEM_TYPE_ZABBIX_ACTIVE,
'value_type' => ITEM_VALUE_TYPE_UINT64,
'delay' => '1s'
],
[
'name' => 'Agent hostname',
'key_' => 'agent.hostname',
'type' => ITEM_TYPE_ZABBIX,
'value_type' => ITEM_VALUE_TYPE_TEXT,
'delay' => '1s'
]
]
]
]);
self::$hostids = $result['hostids'];
self::$itemids = $result['itemids'];
return true;
}
/**
* Component configuration provider for agent related tests.
*
* @return array
*/
public function agentConfigurationProvider() {
return [
self::COMPONENT_SERVER => [
'UnreachablePeriod' => 5,
'UnavailableDelay' => 5,
'UnreachableDelay' => 1,
'DebugLevel' => 4
],
self::COMPONENT_AGENT => [
'Hostname' => 'agent',
'ServerActive' => '127.0.0.1'
]
];
}
/**
* Test if server will disable agent checks if agent is not accessible.
*
* @required-components server
* @configurationDataProvider agentConfigurationProvider
* @hosts agent
*/
public function testDataCollection_checkHostAvailability() {
self::waitForLogLineToBePresent(self::COMPONENT_SERVER,
'temporarily disabling Zabbix agent checks on host "agent": interface unavailable'
);
self::waitForLogLineToBePresent(self::COMPONENT_SERVER, 'update interface set');
self::waitForLogLineToBePresent(self::COMPONENT_SERVER, 'commit;');
$this->reloadConfigurationCache();
$data = $this->call('hostinterface.get', [
'output' => ['available'],
'hostids' => self::$hostids['agent'],
'filter' => [
'type' => 1,
'main' => 1
]
]);
$this->assertTrue(is_array($data['result']));
$this->assertEquals(1, count($data['result']));
$this->assertEquals(INTERFACE_AVAILABLE_FALSE, $data['result'][0]['available']);
}
/**
* Test if both active and passive agent checks are processed.
*
* @required-components server, agent
* @configurationDataProvider agentConfigurationProvider
* @hosts agent
*/
public function testDataCollection_checkAgentData() {
self::waitForLogLineToBePresent(self::COMPONENT_SERVER, [
'enabling Zabbix agent checks on host "agent": interface became available',
'resuming Zabbix agent checks on host "agent": connection restored'
]);
$passive_data = $this->call('history.get', [
'itemids' => self::$itemids['agent:agent.ping'],
'history' => ITEM_VALUE_TYPE_UINT64
]);
foreach ($passive_data['result'] as $item) {
$this->assertEquals(1, $item['value']);
}
// Retrieve history data from API as soon it is available.
$active_data = $this->callUntilDataIsPresent('history.get', [
'itemids' => self::$itemids['agent:agent.hostname'],
'history' => ITEM_VALUE_TYPE_TEXT
]);
foreach ($active_data['result'] as $item) {
$this->assertEquals('agent', $item['value']);
}
}
/**
* Test if custom active checks are processed.
*
* @required-components server
* @hosts custom_agent
*/
public function testDataCollection_checkCustomActiveChecks() {
$host = 'custom_agent';
$items = [];
// Retrieve item data from API.
$response = $this->call('item.get', [
'hostids' => self::$hostids['custom_agent'],
'output' => ['itemid', 'name', 'key_', 'type', 'value_type']
]);
foreach ($response['result'] as $item) {
if ($item['type'] != ITEM_TYPE_ZABBIX_ACTIVE) {
continue;
}
$items[$item['key_']] = $item;
}
$values = [];
$clock = time() - 1;
$checks = $this->getActiveAgentChecks($host);
foreach ($checks as $i => $check) {
$matches = null;
$value = (preg_match('/^.*\[(.*)\]$/', $check['key'], $matches) === 1) ? $matches[1] : microtime();
$this->assertArrayHasKey($check['key'], $items);
$values[$items[$check['key']]['itemid']] = [
'host' => $host,
'key' => $check['key'],
'value' => $value,
'clock' => $clock,
'ns' => $i
];
unset($items[$check['key']]);
}
$this->assertEmpty($items);
$this->sendAgentValues(array_values($values));
// Retrieve history data from API as soon it is available.
$data = $this->callUntilDataIsPresent('history.get', [
'itemids' => array_keys($values),
'history' => ITEM_VALUE_TYPE_TEXT
]);
foreach ($data['result'] as $item) {
$value = $values[$item['itemid']];
foreach (['value', 'clock', 'ns'] as $field) {
$this->assertEquals($value[$field], $item[$field]);
}
}
}
/**
* Component configuration provider for proxy related tests.
*
* @return array
*/
public function proxyConfigurationProvider() {
return [
self::COMPONENT_SERVER => [
'UnreachablePeriod' => 5,
'UnavailableDelay' => 5,
'UnreachableDelay' => 1,
'DebugLevel' => 4
],
self::COMPONENT_PROXY => [
'UnreachablePeriod' => 5,
'UnavailableDelay' => 5,
'UnreachableDelay' => 1,
'DebugLevel' => 4,
'Hostname' => 'proxy',
'Server' => '127.0.0.1:'.self::getConfigurationValue(self::COMPONENT_SERVER, 'ListenPort')
],
self::COMPONENT_AGENT => [
'Hostname' => 'proxy_agent',
'ServerActive' => '127.0.0.1:'.self::getConfigurationValue(self::COMPONENT_PROXY, 'ListenPort')
]
];
}
/**
* Test if both active and passive agent checks are processed.
*
* @required-components server, proxy, agent
* @configurationDataProvider proxyConfigurationProvider
* @hosts proxy_agent
*/
public function testDataCollection_checkProxyData() {
self::waitForLogLineToBePresent(self::COMPONENT_SERVER, 'sending configuration data to proxy "proxy"');
self::waitForLogLineToBePresent(self::COMPONENT_PROXY, 'received configuration data from server');
self::waitForLogLineToBePresent(self::COMPONENT_PROXY, [
'enabling Zabbix agent checks on host "proxy_agent": interface became available',
'resuming Zabbix agent checks on host "proxy_agent": connection restored'
]);
$passive_data = $this->call('history.get', [
'itemids' => self::$itemids['proxy_agent:agent.ping'],
'history' => ITEM_VALUE_TYPE_UINT64
]);
foreach ($passive_data['result'] as $item) {
$this->assertEquals(1, $item['value']);
}
// Retrieve history data from API as soon it is available.
$active_data = $this->callUntilDataIsPresent('history.get', [
'itemids' => self::$itemids['proxy_agent:agent.hostname'],
'history' => ITEM_VALUE_TYPE_TEXT
]);
foreach ($active_data['result'] as $item) {
$this->assertEquals('proxy_agent', $item['value']);
}
}
/**
* Test incremental pre-processing manager cache refresh.
*
* @required-components server
*/
public function testDataCollection_preprocManagerCacheRefresh() {
$response = $this->call('host.create', [
[
'host' => 'trapper_host',
'interfaces' => [
'type' => 1,
'main' => 1,
'useip' => 1,
'ip' => '127.0.0.1',
'dns' => '',
'port' => $this->getConfigurationValue(self::COMPONENT_AGENT, 'ListenPort')
],
'groups' => [['groupid' => 4]],
'status' => HOST_STATUS_MONITORED
]
]);
$this->assertArrayHasKey('hostids', $response['result']);
$this->assertArrayHasKey(0, $response['result']['hostids']);
$hostid = $response['result']['hostids'][0];
$response = $this->call('item.create', [
'hostid' => $hostid,
'name' => 'trap',
'key_' => 'trap',
'type' => ITEM_TYPE_TRAPPER,
'value_type' => ITEM_VALUE_TYPE_UINT64,
'preprocessing' => [[
'params' => '100',
'type' => 1,
'error_handler' => 1,
'error_handler_params' => ''
]]
]);
$this->assertArrayHasKey('itemids', $response['result']);
$this->assertEquals(1, count($response['result']['itemids']));
$itemid = $response['result']['itemids'][0];
$this->reloadConfigurationCache(self::COMPONENT_SERVER);
$this->sendSenderValue('trapper_host', 'trap', 1, self::COMPONENT_SERVER);
$response = $this->callUntilDataIsPresent('history.get', [
'sortfield' => 'clock',
'sortorder' => 'DESC',
'limit' => 1,
'itemids' => [$itemid]
], 60, 1);
$this->assertArrayHasKey('result', $response);
$this->assertEquals(1, count($response['result']));
$this->assertArrayHasKey('value', $response['result'][0]);
$this->assertEquals(100, $response['result'][0]['value']);
$response = $this->call('item.update', [
'itemid' => $itemid,
'preprocessing' => [[
'params' => '200',
'type' => 1,
'error_handler' => 1,
'error_handler_params' => ''
]]
]);
$this->assertArrayHasKey('itemids', $response['result']);
$this->assertEquals(1, count($response['result']['itemids']));
$this->reloadConfigurationCache(self::COMPONENT_SERVER);
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, "finished forced reloading of the configuration cache", true, 60, 1);
$this->sendSenderValue('trapper_host', 'trap', 2, self::COMPONENT_SERVER);
$response = $this->callUntilDataIsPresent('history.get', [
'sortfield' => 'clock',
'sortorder' => 'DESC',
'limit' => 1,
'itemids' => [$itemid]
], 60, 1);
$this->assertArrayHasKey('result', $response);
$this->assertEquals(1, count($response['result']));
$this->assertArrayHasKey('value', $response['result'][0]);
$this->assertEquals(400, $response['result'][0]['value']);
}
}