'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()); } }