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.

221 lines
8.9 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 dirname(__FILE__).'/../../include/CWebTest.php';
require_once dirname(__FILE__).'/../../include/helpers/CDataHelper.php';
class testSystemInformation extends CWebTest {
const FAILOVER_DELAY = 8;
public static $active_lastaccess;
public static $update_timestamp;
public static $standby_lastaccess;
public static $stopped_lastaccess;
public static $unavailable_lastaccess;
public static $skip_fields;
/**
* Function inserts HA cluster data into ha_node table.
*/
public static function prepareHANodeData() {
global $DB;
self::$active_lastaccess = time();
self::$standby_lastaccess = self::$active_lastaccess - 1;
self::$stopped_lastaccess = self::$active_lastaccess - 240;
self::$unavailable_lastaccess = self::$active_lastaccess - 180105;
$nodes = [
[
'ha_nodeid' => 'ckv2kclpg0001pt7pseinx5is',
'name' => 'Standby node',
'address' => '192.168.133.195',
'port' => 10055,
'lastaccess' => self::$standby_lastaccess,
'status' => 0,
'ha_sessionid' => 'ckv6hh1730000q17pci1gocjy'
],
[
'ha_nodeid' => 'ckv2kfmqj0001pipjf0g4pr20',
'name' => 'Stopped node',
'address' => '192.168.133.192',
'port' => 10025,
'lastaccess' => self::$stopped_lastaccess,
'status' => 1,
'ha_sessionid' => 'ckv6gyurt0000vfpjp7b8nad4'
],
[
'ha_nodeid' => 'ckvaw8yny0001l07pm1bk14y5',
'name' => 'Unavailable node',
'address' => '192.168.133.206',
'port' => 10051,
'lastaccess' => self::$unavailable_lastaccess,
'status' => 2,
'ha_sessionid' => 'ckvaw8yie0000kr7pzk6nd5ok'
],
[
'ha_nodeid' => 'ckvaw9wlf0001tn7psxgh3wfo',
'name' => 'Active node',
'address' => $DB['SERVER'],
'port' => 0,
'lastaccess' => self::$active_lastaccess,
'status' => 3,
'ha_sessionid' => 'ckvaw9wjo0000td7p8j66e74x'
]
];
// Update Zabbix frontend config to make sure that the address of the active node is shown correctly in tests.
$file_path = dirname(__FILE__).'/../../../conf/zabbix.conf.php';
$pattern = array('/[$]ZBX_SERVER/','/[$]ZBX_SERVER_PORT/');
$replace = array('// $ZBX_SERVER','// $ZBX_SERVER_PORT');
$content = preg_replace($pattern, $replace, file_get_contents($file_path), 1);
file_put_contents($file_path, $content);
// Insert HA cluster data into ha_node table.
foreach ($nodes as $node) {
DBexecute('INSERT INTO ha_node (ha_nodeid, name, address, port, lastaccess, status, ha_sessionid) '.
'VALUES ('.zbx_dbstr($node['ha_nodeid']).', '.zbx_dbstr($node['name']).', '.zbx_dbstr($node['address']).
', '.$node['port'].', '.$node['lastaccess'].', '.$node['status'].', '.zbx_dbstr($node['ha_sessionid']).');'
);
}
// Get the time when config is updated - it is needed to know how long to wait until update of Zabbix server status.
self::$update_timestamp = time();
}
// Change failover delay not to wait too long for server to update its status.
public static function changeFailoverDelay() {
DBexecute('UPDATE config SET ha_failover_delay='.self::FAILOVER_DELAY);
}
/**
* Function that checks how a running HA cluster info is displayed in system information widget or report.
*
* @param integer $dashboardid id of the dashboard that the widgets are located in.
*/
public function assertEnabledHACluster($dashboardid = null) {
global $DB;
self::$skip_fields = [];
$url = (!$dashboardid) ? 'zabbix.php?action=report.status' : 'zabbix.php?action=dashboard.view&dashboardid='.$dashboardid;
// Wait for frontend to get the new config from updated zabbix.conf.php file.
sleep((int) ini_get('opcache.revalidate_freq') + 1);
$this->page->login()->open($url)->waitUntilReady();
$current_time = time();
if (!$dashboardid) {
$nodes_table = $this->query('xpath://table[@class="list-table sticky-header sticky-footer"]')->asTable()->one();
$server_address = $this->query('xpath://th[text()="Zabbix server is running"]/../td[2]')->one();
}
else {
$dashboard = CDashboardElement::find()->waitUntilReady()->one();
$nodes_table = $dashboard->getWidget('High availability nodes view')->query('xpath:.//table')->asTable()->one();
$server_address = $dashboard->getWidget('System stats view')->query('xpath:.//tbody/tr[1]/td[2]')->one();
}
// Define expected absolute timestamps for calculating the lastaccess value.
$nodes = [
'Active node' => self::$active_lastaccess,
'Unavailable node' => self::$unavailable_lastaccess,
'Stopped node' => self::$stopped_lastaccess,
'Standby node' => self::$standby_lastaccess
];
/**
* The below foreach cycle compares lastaccess as time difference for each node in the widget or part of report
* that displays the list of nodes and excludes corresponding element from screenshot.
*/
foreach ($nodes as $name => $lastaccess_db) {
$row = $nodes_table->findRow('Name', $name);
$last_seen = $row->getColumn('Last access');
self::$skip_fields[] = $last_seen;
/**
* Converting unix timestamp difference into difference in time units and creating an array of such reference
* values. This is required because several seconds might have passed from defining $current_time and
* loading the page. Afterwards, the presence of the actual last access value in this array is determined.
*/
$last_expected = [];
// Negative $i values are considered because current_time may be defined before data in sysinfo widget gets displayed.
for ($i = -2; $i <= 6; $i++) {
$last_expected[] = convertUnitsS($current_time - $lastaccess_db - $i);
}
$last_actual = $last_seen->getText();
$this->assertContains($last_actual, $last_expected, $last_actual.' not in ['.implode(', ', $last_expected).']');
// Check Zabbix server address and port for each record in the HA cluster nodes table.
if ($name === 'Active node') {
self::$skip_fields[] = $row->getColumn('Address');
$this->assertEquals($DB['SERVER'].':0', $row->getColumn('Address')->getText());
}
}
/**
* Check and hide the active Zabbix server address in widget that is working in System stats mode or in the part
* of the report that displays the overall system statistics.
*/
$this->assertEquals($DB['SERVER'].':0', $server_address->getText());
self::$skip_fields[] = $server_address;
// Hide the footer of the report as it contains Zabbix version.
if (!$dashboardid) {
self::$skip_fields[] = $this->query('xpath://footer')->one();
}
// Hide frontend version.
self::$skip_fields[] = $this->query('xpath://table[@class="list-table sticky-header"]/tbody/tr[3]/td[1]')->one();
// Check and hide the text of messages, because they contain ip addresses of the current host.
$error_text = "Connection to Zabbix server \"".$DB['SERVER'].":0\" failed. Possible reasons:\n".
"1. Incorrect \"NodeAddress\" or \"ListenPort\" in the \"zabbix_server.conf\" or server IP/DNS override in the \"zabbix.conf.php\";\n".
"2. Incorrect DNS server configuration.\n".
"Failed to parse address \"".$DB['SERVER']."\"";
$messages = CMessageElement::find()->all();
foreach ($messages as $message) {
$this->assertTrue($message->hasLine($error_text));
self::$skip_fields[] = $message;
}
}
/**
* Function checks that Zabbix server status is updated after failover delay passes and frontend config is re-validated.
*
* @param integer $dashboardid id of the dashboard that the widgets are located in.
*/
public function assertServerStatusAfterFailover($dashboardid = null) {
$url = (!$dashboardid) ? 'zabbix.php?action=report.status' : 'zabbix.php?action=dashboard.view&dashboardid='.$dashboardid;
$this->page->login()->open($url)->waitUntilReady();
$table = $this->query('xpath://table[@class="list-table sticky-header"]')->asTable()->waitUntilVisible()->one();
// Check that before failover delay passes frontend thinks that Zabbix server is running.
$this->assertEquals('Yes', $table->findRow('Parameter', 'Zabbix server is running')->getColumn('Value')->getText());
// Wait for failover delay to pass.
sleep(self::$update_timestamp + self::FAILOVER_DELAY - time());
// Check that after failover delay passes frontend re-validates Zabbix server status.
$this->page->refresh();
$this->assertEquals('No', $table->findRow('Parameter', 'Zabbix server is running')->getColumn('Value')->getText());
}
}