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.
1106 lines
34 KiB
1106 lines
34 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';
|
|
|
|
/**
|
|
* Test suite for action notifications
|
|
*
|
|
* @required-components server
|
|
* @configurationDataProvider serverConfigurationProvider
|
|
* @backup items,actions,triggers,alerts
|
|
* @hosts test_actions
|
|
*/
|
|
class testEscalations extends CIntegrationTest {
|
|
|
|
private static $hostid;
|
|
private static $triggerid;
|
|
private static $maint_start_tm;
|
|
private static $trigger_actionid;
|
|
private static $scriptid_problem;
|
|
private static $scriptid_recovery;
|
|
|
|
const TRAPPER_ITEM_NAME = 'trap';
|
|
const HOST_NAME = 'test_actions';
|
|
const COMMAND_PROBLEM = 'echo "problem"';
|
|
const COMMAND_RECOVERY = 'echo "recovery"';
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function prepareData() {
|
|
// Create host "testhost".
|
|
$response = $this->call('host.create', [
|
|
'host' => self::HOST_NAME,
|
|
'interfaces' => [
|
|
'type' => 1,
|
|
'main' => 1,
|
|
'useip' => 1,
|
|
'ip' => '127.0.0.1',
|
|
'dns' => '',
|
|
'port' => $this->getConfigurationValue(self::COMPONENT_AGENT, 'ListenPort')
|
|
],
|
|
'groups' => ['groupid' => 4]
|
|
]);
|
|
|
|
$this->assertArrayHasKey('hostids', $response['result']);
|
|
$this->assertArrayHasKey(0, $response['result']['hostids']);
|
|
self::$hostid = $response['result']['hostids'][0];
|
|
|
|
// Get host interface ids.
|
|
$response = $this->call('host.get', [
|
|
'output' => ['host'],
|
|
'hostids' => [self::$hostid],
|
|
'selectInterfaces' => ['interfaceid']
|
|
]);
|
|
|
|
$this->assertArrayHasKey(0, $response['result']);
|
|
$this->assertArrayHasKey('interfaces', $response['result'][0]);
|
|
$this->assertArrayHasKey(0, $response['result'][0]['interfaces']);
|
|
|
|
// Create trapper item
|
|
$response = $this->call('item.create', [
|
|
'hostid' => self::$hostid,
|
|
'name' => self::TRAPPER_ITEM_NAME,
|
|
'key_' => self::TRAPPER_ITEM_NAME,
|
|
'type' => ITEM_TYPE_TRAPPER,
|
|
'value_type' => ITEM_VALUE_TYPE_UINT64
|
|
]);
|
|
$this->assertArrayHasKey('itemids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['itemids']));
|
|
|
|
// Create trigger
|
|
$response = $this->call('trigger.create', [
|
|
'description' => 'Trapper received 1',
|
|
'expression' => 'last(/'.self::HOST_NAME.'/'.self::TRAPPER_ITEM_NAME.')>0'
|
|
]);
|
|
$this->assertArrayHasKey('triggerids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['triggerids']));
|
|
self::$triggerid = $response['result']['triggerids'][0];
|
|
|
|
// Create trigger action
|
|
$response = $this->call('action.create', [
|
|
'esc_period' => '1h',
|
|
'eventsource' => EVENT_SOURCE_TRIGGERS,
|
|
'status' => ACTION_STATUS_ENABLED,
|
|
'filter' => [
|
|
'conditions' => [
|
|
[
|
|
'conditiontype' => CONDITION_TYPE_TRIGGER,
|
|
'operator' => CONDITION_OPERATOR_EQUAL,
|
|
'value' => self::$triggerid
|
|
]
|
|
],
|
|
'evaltype' => CONDITION_EVAL_TYPE_AND_OR
|
|
],
|
|
'name' => 'Trapper received 1 (problem) clone',
|
|
'operations' => [
|
|
[
|
|
'esc_period' => 0,
|
|
'esc_step_from' => 1,
|
|
'esc_step_to' => 1,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => ['default_msg' => 1,
|
|
'mediatypeid' => 0
|
|
],
|
|
'opmessage_grp' => [
|
|
['usrgrpid' => 7]
|
|
]
|
|
]
|
|
],
|
|
'pause_suppressed' => 0,
|
|
'recovery_operations' => [
|
|
[
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 1,
|
|
'mediatypeid' => 0
|
|
],
|
|
'opmessage_grp' => [
|
|
['usrgrpid' => 7]
|
|
]
|
|
]
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['actionids']));
|
|
self::$trigger_actionid = $response['result']['actionids'][0];
|
|
|
|
// Enable mediatypes
|
|
$response = $this->call('mediatype.update', [
|
|
'mediatypeid' => 1,
|
|
'status' => 0
|
|
]);
|
|
$this->assertArrayHasKey('mediatypeids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['mediatypeids']));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Component configuration provider for agent related tests.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function serverConfigurationProvider() {
|
|
return [
|
|
self::COMPONENT_SERVER => [
|
|
'DebugLevel' => 4,
|
|
'LogFileSize' => 20
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Component configuration provider for remote command related tests.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function serverConfigurationProviderRemote() {
|
|
return [
|
|
self::COMPONENT_SERVER => [
|
|
'DebugLevel' => 4,
|
|
'LogFileSize' => 20,
|
|
'Timeout' => 30
|
|
],
|
|
self::COMPONENT_AGENT => [
|
|
'Hostname' => self::HOST_NAME,
|
|
'ServerActive' => '127.0.0.1:'.self::getConfigurationValue(self::COMPONENT_SERVER,
|
|
'ListenPort', 10051),
|
|
'AllowKey' => 'system.run[*]',
|
|
'LogRemoteCommands' => 1
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @backup actions,alerts,history_uint,history,problem,events
|
|
*/
|
|
public function testEscalations_disabledAction() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'status' => 1
|
|
]);
|
|
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['actionids']));
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 1);
|
|
|
|
// Check if there are no alerts for this action
|
|
$response = $this->call('alert.get', [
|
|
'actionids' => [self::$trigger_actionid]
|
|
]);
|
|
$this->assertEmpty($response['result']);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
}
|
|
|
|
/**
|
|
* @backup alerts,triggers,history_uint,history,problem,events
|
|
*/
|
|
public function testEscalations_disabledTrigger() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$response = $this->call('trigger.update', [
|
|
'triggerid' => self::$triggerid,
|
|
'status' => 1
|
|
]);
|
|
|
|
$this->assertArrayHasKey('triggerids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['triggerids']));
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 2);
|
|
|
|
// Check if there are no alerts for this action
|
|
$response = $this->call('alert.get', [
|
|
'actionids' => [self::$trigger_actionid]
|
|
]);
|
|
$this->assertEmpty($response['result']);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
}
|
|
|
|
/**
|
|
* Test maintenance scenario:
|
|
* disable pause_suppressed
|
|
* maintenance on
|
|
* event -> alert
|
|
* recovery -> alert
|
|
*
|
|
* @backup alerts,history,history_uint,maintenances,events,problem
|
|
*/
|
|
public function testEscalations_checkScenario1() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$this->reloadConfigurationCache();
|
|
// Create maintenance period
|
|
self::$maint_start_tm = time();
|
|
$maint_end_tm = self::$maint_start_tm + 60 * 2;
|
|
|
|
$response = $this->call('maintenance.create', [
|
|
'name' => 'Test maintenance',
|
|
'hosts' => ['hostid' => self::$hostid],
|
|
'active_since' => self::$maint_start_tm,
|
|
'active_till' => $maint_end_tm,
|
|
'tags_evaltype' => MAINTENANCE_TAG_EVAL_TYPE_AND_OR,
|
|
'timeperiods' => [
|
|
'timeperiod_type' => TIMEPERIOD_TYPE_ONETIME,
|
|
'period' => 300,
|
|
'start_date' => self::$maint_start_tm
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('maintenanceids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['maintenanceids']));
|
|
$maintenance_id = $response['result']['maintenanceids'][0];
|
|
|
|
$this->reloadConfigurationCache();
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of zbx_dc_update_maintenances()', true);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 3);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid]
|
|
], 5, 2);
|
|
$this->assertArrayHasKey(0, $response['result']);
|
|
$this->assertEquals(0, $response['result'][0]['p_eventid']);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_execute()', true, 120);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_execute()', true, 10, 3);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid],
|
|
'sortfield' => 'alertid'
|
|
], 5, 2);
|
|
$this->assertArrayHasKey(1, $response['result']);
|
|
$this->assertNotEquals(0, $response['result'][1]['p_eventid']);
|
|
}
|
|
|
|
/**
|
|
* Test maintenance scenario:
|
|
* event -> alert
|
|
* maintenance on
|
|
* recovery -> alert
|
|
*
|
|
* @backup actions,alerts,history_uint,maintenances
|
|
*/
|
|
public function testEscalations_checkScenario2() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'pause_suppressed' => 1
|
|
]);
|
|
// Create maintenance period
|
|
self::$maint_start_tm = time() + 10;
|
|
$maint_end_tm = self::$maint_start_tm + 60 * 2;
|
|
|
|
$response = $this->call('maintenance.create', [
|
|
'name' => 'Test maintenance',
|
|
'hosts' => ['hostid' => self::$hostid],
|
|
'active_since' => self::$maint_start_tm,
|
|
'active_till' => $maint_end_tm,
|
|
'tags_evaltype' => MAINTENANCE_TAG_EVAL_TYPE_AND_OR,
|
|
'timeperiods' => [
|
|
'timeperiod_type' => TIMEPERIOD_TYPE_ONETIME,
|
|
'period' => 300,
|
|
'start_date' => self::$maint_start_tm
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('maintenanceids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['maintenanceids']));
|
|
$maintenance_id = $response['result']['maintenanceids'][0];
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 4);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_execute()', true, 120);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_execute()', true, 10, 3);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid]
|
|
], 5, 2);
|
|
$this->assertArrayHasKey(0, $response['result']);
|
|
$this->assertEquals(0, $response['result'][0]['p_eventid']);
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER,
|
|
'End of zbx_dc_update_maintenances() started:1 stopped:0 running:1', true);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_recover()', true, 120);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_recover()', true);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid],
|
|
'sortfield' => 'alertid'
|
|
], 5, 2);
|
|
$this->assertArrayHasKey(1, $response['result']);
|
|
$this->assertNotEquals(0, $response['result'][1]['p_eventid']);
|
|
}
|
|
|
|
/**
|
|
* Test maintenance scenario:
|
|
* maintenance on
|
|
* event -> nothing
|
|
* maintenance off -> alert
|
|
* recovery -> alert
|
|
*
|
|
* @backup actions,alerts,history_uint,maintenances
|
|
*/
|
|
public function testEscalations_checkScenario3() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'pause_suppressed' => 1
|
|
]);
|
|
// Create maintenance period
|
|
self::$maint_start_tm = time();
|
|
$maint_end_tm = self::$maint_start_tm + 60 * 2;
|
|
|
|
$response = $this->call('maintenance.create', [
|
|
'name' => 'Test maintenance',
|
|
'hosts' => ['hostid' => self::$hostid],
|
|
'active_since' => self::$maint_start_tm,
|
|
'active_till' => $maint_end_tm,
|
|
'tags_evaltype' => MAINTENANCE_TAG_EVAL_TYPE_AND_OR,
|
|
'timeperiods' => [
|
|
'timeperiod_type' => TIMEPERIOD_TYPE_ONETIME,
|
|
'period' => 300,
|
|
'start_date' => self::$maint_start_tm
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('maintenanceids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['maintenanceids']));
|
|
$maintenance_id = $response['result']['maintenanceids'][0];
|
|
|
|
$this->reloadConfigurationCache();
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER,
|
|
'End of zbx_dc_update_maintenances() started:1 stopped:0 running:1', true);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 5);
|
|
|
|
$response = $this->call('alert.get', [
|
|
'actionids' => [self::$trigger_actionid]
|
|
]);
|
|
$this->assertEmpty($response['result']);
|
|
|
|
$response = $this->call('maintenance.delete', [
|
|
$maintenance_id
|
|
]);
|
|
$this->assertArrayHasKey('maintenanceids', $response['result']);
|
|
$this->assertEquals($maintenance_id, $response['result']['maintenanceids'][0]);
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In zbx_dc_update_maintenances()|In escalation_execute()', true, 120, null, true);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of zbx_dc_update_maintenances()|End of escalation_execute()', true, null, 3, true);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_execute()|In zbx_dc_update_maintenances()', true, 120, null, true);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_execute()|End of zbx_dc_update_maintenances()', true, null, 3, true);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid]
|
|
], 5, 2);
|
|
$this->assertArrayHasKey(0, $response['result']);
|
|
$this->assertEquals(0, $response['result'][0]['p_eventid']);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_recover()', true, 120);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_recover()', true);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid],
|
|
'sortfield' => 'alertid'
|
|
], 5, 2);
|
|
$this->assertArrayHasKey(1, $response['result']);
|
|
$this->assertNotEquals(0, $response['result'][1]['p_eventid']);
|
|
}
|
|
|
|
/**
|
|
* Test cancelled escalation (disabled trigger)
|
|
*
|
|
* @backup actions,alerts,events,problem,history_uint,hosts,users
|
|
*/
|
|
public function testEscalations_checkScenario4() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'operations' => [
|
|
[
|
|
'esc_period' => '1m',
|
|
'esc_step_from' => 1,
|
|
'esc_step_to' => 1,
|
|
'evaltype' => 0,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'mediatypeid' => 1,
|
|
'message' => 'Problem',
|
|
'subject' => 'Problem'
|
|
],
|
|
'opmessage_grp' => [['usrgrpid' => 7]]
|
|
],
|
|
[
|
|
'esc_period' => '1m',
|
|
'esc_step_from' => 2,
|
|
'esc_step_to' => 2,
|
|
'evaltype' => 0,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'mediatypeid' => 1,
|
|
'message' => 'Problem',
|
|
'subject' => 'Problem'
|
|
],
|
|
'opmessage_grp' => [['usrgrpid' => 7]]
|
|
]
|
|
]
|
|
]);
|
|
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertArrayHasKey(0, $response['result']['actionids']);
|
|
$response = $this->call('user.update', [
|
|
'userid' => 1,
|
|
'medias' => [
|
|
[
|
|
'mediatypeid' => 1,
|
|
'sendto' => 'test@local.local'
|
|
]
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('userids', $response['result']);
|
|
$this->assertArrayHasKey(0, $response['result']['userids']);
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 6);
|
|
|
|
$response = $this->call('trigger.update', [
|
|
'triggerid' => self::$triggerid,
|
|
'status' => 1
|
|
]);
|
|
$this->assertArrayHasKey('triggerids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['triggerids']));
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_cancel()', true, 120);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid],
|
|
'sortfield' => 'alertid'
|
|
], 5, 2);
|
|
$esc_msg = 'NOTE: Escalation canceled';
|
|
$this->assertArrayHasKey(1, $response['result']);
|
|
$this->assertEquals(0, strncmp($esc_msg, $response['result'][1]['message'], strlen($esc_msg)));
|
|
|
|
// trigger value is not updated during configuration cache sync (only initialized)
|
|
// therefore need to restore it manually by sending OK value
|
|
$response = $this->call('trigger.update', [
|
|
'triggerid' => self::$triggerid,
|
|
'status' => 0
|
|
]);
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
|
|
// test ability to disable notifications about cancelled escalations
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'notify_if_canceled' => 0
|
|
]);
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertArrayHasKey(0, $response['result']['actionids']);
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 10);
|
|
|
|
$response = $this->call('trigger.update', [
|
|
'triggerid' => self::$triggerid,
|
|
'status' => 1
|
|
]);
|
|
|
|
$this->assertArrayHasKey('triggerids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['triggerids']));
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_cancel()', true, 120);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => [self::$trigger_actionid],
|
|
'sortfield' => 'alertid',
|
|
'sortorder' => 'DESC'
|
|
], 5, 2);
|
|
$this->assertArrayHasKey(0, $response['result']);
|
|
$this->assertNotEquals(0, strncmp($esc_msg, $response['result'][0]['message'], strlen($esc_msg)));
|
|
|
|
// revert to defaults, restore trigger status and value
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'notify_if_canceled' => 1
|
|
]);
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertArrayHasKey(0, $response['result']['actionids']);
|
|
|
|
$response = $this->call('trigger.update', [
|
|
'triggerid' => self::$triggerid,
|
|
'status' => 0
|
|
]);
|
|
$this->assertArrayHasKey('triggerids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['triggerids']));
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
}
|
|
|
|
/**
|
|
* Test normal escalation with multiple escalations steps
|
|
*
|
|
* @backup alerts,actions
|
|
*/
|
|
public function testEscalations_checkScenario5() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$this->reloadConfigurationCache();
|
|
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'esc_period' => '1m',
|
|
'operations' => [
|
|
[
|
|
'esc_period' => 0,
|
|
'esc_step_from' => 1,
|
|
'esc_step_to' => 1,
|
|
'evaltype' => 0,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'mediatypeid' => 0,
|
|
'message' => 'Cause problem 1',
|
|
'subject' => 'Cause problem 1'
|
|
],
|
|
'opmessage_grp' => [['usrgrpid' => 7]]
|
|
],
|
|
[
|
|
'esc_period' => 0,
|
|
'esc_step_from' => 2,
|
|
'esc_step_to' => 2,
|
|
'evaltype' => 0,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'mediatypeid' => 0,
|
|
'message' => 'Cause problem 2',
|
|
'subject' => 'Cause problem 2'
|
|
],
|
|
'opmessage_grp' => [['usrgrpid' => 7]]
|
|
]
|
|
]
|
|
]);
|
|
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertArrayHasKey(0, $response['result']['actionids']);
|
|
|
|
// create items, triggers, actions for testing symptom events
|
|
$pause_symptoms = [
|
|
1 => ACTION_PAUSE_SYMPTOMS_TRUE,
|
|
2 => ACTION_PAUSE_SYMPTOMS_FALSE
|
|
];
|
|
$trapper_keys = [];
|
|
$symptom_triggerids = [];
|
|
$symptom_actionids = [];
|
|
|
|
foreach ([1, 2] as $i) {
|
|
// Create trapper item
|
|
$name = $key = self::TRAPPER_ITEM_NAME."_s".(string)$i;
|
|
$trapper_keys[$i] = $key;
|
|
$response = $this->call('item.create', [
|
|
'hostid' => self::$hostid,
|
|
'name' => $name,
|
|
'key_' => $key,
|
|
'type' => ITEM_TYPE_TRAPPER,
|
|
'value_type' => ITEM_VALUE_TYPE_UINT64
|
|
]);
|
|
$this->assertArrayHasKey('itemids', $response['result']);
|
|
$this->assertCount(1, $response['result']['itemids']);
|
|
|
|
// Create trigger
|
|
$response = $this->call('trigger.create', [
|
|
'description' => 'Mandatory description',
|
|
'expression' => 'last(/'.self::HOST_NAME.'/'.$key.')>0'
|
|
]);
|
|
$this->assertArrayHasKey('triggerids', $response['result']);
|
|
$this->assertCount(1, $response['result']['triggerids']);
|
|
$symptom_triggerids[$i] = $response['result']['triggerids'][0];
|
|
|
|
// Create action
|
|
$response = $this->call('action.create', [
|
|
'esc_period' => '1m',
|
|
'eventsource' => EVENT_SOURCE_TRIGGERS,
|
|
'status' => ACTION_STATUS_ENABLED,
|
|
'pause_symptoms' => $pause_symptoms[$i],
|
|
'filter' => [
|
|
'conditions' => [
|
|
[
|
|
'conditiontype' => CONDITION_TYPE_TRIGGER,
|
|
'operator' => CONDITION_OPERATOR_EQUAL,
|
|
'value' => $symptom_triggerids[$i]
|
|
]
|
|
],
|
|
'evaltype' => CONDITION_EVAL_TYPE_AND_OR
|
|
],
|
|
'name' => 'Symptom action '.(string)$i,
|
|
'operations' => [
|
|
[
|
|
'esc_period' => 0,
|
|
'esc_step_from' => 1,
|
|
'esc_step_to' => 1,
|
|
'evaltype' => 0,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'mediatypeid' => 0,
|
|
'message' => 'Symptom problem 1',
|
|
'subject' => 'Symptom problem 1'
|
|
],
|
|
'opmessage_grp' => [['usrgrpid' => 7]]
|
|
],
|
|
[
|
|
'esc_period' => 0,
|
|
'esc_step_from' => 2,
|
|
'esc_step_to' => 2,
|
|
'evaltype' => 0,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'mediatypeid' => 0,
|
|
'message' => 'Symptom problem 2',
|
|
'subject' => 'Symptom problem 2'
|
|
],
|
|
'opmessage_grp' => [['usrgrpid' => 7]]
|
|
]
|
|
]
|
|
]);
|
|
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertCount(1, $response['result']['actionids']);
|
|
$symptom_actionids[$i] = $response['result']['actionids'][0];
|
|
}
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
// start all events as causes, because only existing events can be ranked as symptoms
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 7);
|
|
$this->sendSenderValue(self::HOST_NAME, $trapper_keys[1], 7);
|
|
$this->sendSenderValue(self::HOST_NAME, $trapper_keys[2], 7);
|
|
|
|
$response = $this->callUntilDataIsPresent('problem.get', [
|
|
'output' => ['eventid'],
|
|
'objectids' => [self::$triggerid, $symptom_triggerids[1], $symptom_triggerids[2]]
|
|
]);
|
|
|
|
$this->assertCount(3, $response['result']);
|
|
$this->assertArrayHasKey('eventid', $response['result'][0]);
|
|
$this->assertArrayHasKey('eventid', $response['result'][1]);
|
|
$this->assertArrayHasKey('eventid', $response['result'][2]);
|
|
|
|
$cause_eventid = $response['result'][0]['eventid'];
|
|
|
|
// these events are causes at this point and will be ranked as symptoms later
|
|
$symptom_eventids[1] = $response['result'][1]['eventid'];
|
|
$symptom_eventids[2] = $response['result'][2]['eventid'];
|
|
|
|
// wait until escalation step 1 is completed for all three events
|
|
for ($i = 0; $i < 3; $i++) {
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_execute()', true, 95, 3);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_execute()', true, 10, 3);
|
|
}
|
|
|
|
// rank 2 events as symptom events
|
|
$response = $this->call('event.acknowledge', [
|
|
'eventids' => $symptom_eventids,
|
|
'action' => ZBX_PROBLEM_UPDATE_RANK_TO_SYMPTOM,
|
|
'cause_eventid' => $cause_eventid
|
|
]);
|
|
|
|
$this->assertArrayHasKey('result', $response);
|
|
$this->assertArrayHasKey('eventids', $response['result']);
|
|
$this->assertCount(2, $response['result']['eventids']);
|
|
|
|
// Escalations are expected for 2 events:
|
|
// 1. the cause event;
|
|
// 2. one symptom event with ACTION_PAUSE_SYMPTOMS_FALSE.
|
|
for ($i = 0; $i < 2; $i++) {
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_execute()', true, 95, 3);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_execute()', true, 10, 3);
|
|
}
|
|
|
|
// check alerts for the cause event
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'output' => 'extend',
|
|
'actionids' => [self::$trigger_actionid],
|
|
'sortfield' => 'alertid'
|
|
], 5, 2);
|
|
|
|
// 2 escalations are expected
|
|
$this->assertCount(2, $response['result']);
|
|
$this->assertEquals(1, $response['result'][0]['esc_step']);
|
|
$this->assertEquals(2, $response['result'][1]['esc_step']);
|
|
|
|
// check alerts for the symptom event with ACTION_PAUSE_SYMPTOMS_TRUE
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'output' => 'extend',
|
|
'actionids' => $symptom_actionids[1],
|
|
'sortfield' => 'alertid'
|
|
], 5, 2);
|
|
|
|
// 1 escalation is expected
|
|
$this->assertCount(1, $response['result']);
|
|
$this->assertEquals(1, $response['result'][0]['esc_step']);
|
|
|
|
// check alerts for the symptom event with ACTION_PAUSE_SYMPTOMS_FALSE
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'output' => 'extend',
|
|
'actionids' => $symptom_actionids[2],
|
|
'sortfield' => 'alertid'
|
|
], 5, 2);
|
|
|
|
// 2 escalations are expected
|
|
$this->assertCount(2, $response['result']);
|
|
$this->assertEquals(1, $response['result'][0]['esc_step']);
|
|
$this->assertEquals(2, $response['result'][1]['esc_step']);
|
|
|
|
// stop events
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
$this->sendSenderValue(self::HOST_NAME, $trapper_keys[1], 0);
|
|
$this->sendSenderValue(self::HOST_NAME, $trapper_keys[2], 0);
|
|
}
|
|
|
|
/**
|
|
* Test unfinished webhook
|
|
*testEscalations_checkUnfinishedAlerts
|
|
* @backup actions, alerts, history_uint, media_type, users, media, events, problem
|
|
*/
|
|
public function testEscalations_checkUnfinishedAlerts() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$this->reloadConfigurationCache();
|
|
|
|
// Create webhook mediatype
|
|
$script_code = <<<HEREDOC
|
|
var params = JSON.parse(value);
|
|
|
|
if (!(params.event_value === '0' || params.event_update_status === '1')) {
|
|
var now = new Date().getTime();
|
|
while (new Date().getTime() < now + 11000) { /* do nothing */ }
|
|
}
|
|
|
|
return {};
|
|
HEREDOC;
|
|
$response = $this->call('mediatype.create', [
|
|
'script' => $script_code,
|
|
'name' => 'Long executing webhook',
|
|
'timeout' => '30s',
|
|
'type' => MEDIA_TYPE_WEBHOOK,
|
|
'parameters' => [
|
|
[
|
|
'name' => 'event_value',
|
|
'value' => '{EVENT.VALUE}'
|
|
],
|
|
[
|
|
'name' => 'event_update_status',
|
|
'value' => '{EVENT.SOURCE}'
|
|
]
|
|
],
|
|
'content_type' => 1,
|
|
'status' => 0
|
|
]);
|
|
$this->assertArrayHasKey('mediatypeids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['mediatypeids']));
|
|
$mediatypeid = $response['result']['mediatypeids'][0];
|
|
|
|
$response = $this->call('user.update', [
|
|
'userid' => 1,
|
|
'medias' => [
|
|
[
|
|
'mediatypeid' => $mediatypeid,
|
|
'sendto' => 'q'
|
|
]
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('userids', $response['result']);
|
|
$this->assertArrayHasKey(0, $response['result']['userids']);
|
|
|
|
// Create action
|
|
$response = $this->call('action.create', [
|
|
'esc_period' => '1h',
|
|
'eventsource' => 0,
|
|
'status' => 0,
|
|
'filter' => [
|
|
'conditions' => [
|
|
[
|
|
'conditiontype' => CONDITION_TYPE_TRIGGER,
|
|
'operator' => CONDITION_OPERATOR_EQUAL,
|
|
'value' => self::$triggerid
|
|
]
|
|
],
|
|
'evaltype' => 0
|
|
],
|
|
'name' => 'Trapper received 1 (unfinished alert check)',
|
|
'operations' => [
|
|
[
|
|
'esc_period' => 0,
|
|
'esc_step_from' => 1,
|
|
'esc_step_to' => 1,
|
|
'operationtype' => OPERATION_TYPE_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'mediatypeid' => $mediatypeid,
|
|
'subject' => 's',
|
|
'message' => 's'
|
|
],
|
|
'opmessage_grp' => [['usrgrpid' => 7]]
|
|
]
|
|
],
|
|
'pause_suppressed' => 0,
|
|
'recovery_operations' => [
|
|
[
|
|
'operationtype' => OPERATION_TYPE_RECOVERY_MESSAGE,
|
|
'opmessage' => [
|
|
'default_msg' => 0,
|
|
'subject' => 'R',
|
|
'message' => 'R'
|
|
]
|
|
]
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['actionids']));
|
|
$actionid = $response['result']['actionids'];
|
|
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'status' => 1
|
|
]);
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 8);
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_execute()', true, 95, 3);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_execute()', true, 10, 3);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => $actionid
|
|
], 5, 2);
|
|
$this->assertCount(1, $response['result']);
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_recover()', true, 200);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_recover()', true);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => $actionid
|
|
], 5, 2);
|
|
$this->assertCount(2, $response['result']);
|
|
}
|
|
|
|
/**
|
|
* Test active remote commands
|
|
*testEscalations_checkActiveCommands
|
|
* @required-components server, agent
|
|
* @configurationDataProvider serverConfigurationProviderRemote
|
|
* @backup actions, alerts, history_uint, media_type, users, media, events, problem
|
|
*/
|
|
public function testEscalations_checkActiveCommands() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
$this->reloadConfigurationCache();
|
|
|
|
// Create remote commands
|
|
$response = $this->call('script.create', [
|
|
'name' => 'Test remote command problem',
|
|
'command' => self::COMMAND_PROBLEM,
|
|
'execute_on' => 0,
|
|
'scope' => 1,
|
|
'type' => 0
|
|
]);
|
|
$this->assertArrayHasKey('scriptids', $response['result']);
|
|
self::$scriptid_problem = $response['result']['scriptids'][0];
|
|
|
|
$response = $this->call('script.create', [
|
|
'name' => 'Test remote command recovery',
|
|
'command' => self::COMMAND_RECOVERY,
|
|
'execute_on' => 0,
|
|
'scope' => 1,
|
|
'type' => 0
|
|
]);
|
|
$this->assertArrayHasKey('scriptids', $response['result']);
|
|
self::$scriptid_recovery = $response['result']['scriptids'][0];
|
|
|
|
// Create active item
|
|
$response = $this->call('item.create', [
|
|
'hostid' => self::$hostid,
|
|
'name' => 'Agent variant',
|
|
'key_' => 'agent.variant',
|
|
'type' => ITEM_TYPE_ZABBIX_ACTIVE,
|
|
'value_type' => ITEM_VALUE_TYPE_UINT64,
|
|
'delay' => '1s'
|
|
]);
|
|
$this->assertArrayHasKey('itemids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['itemids']));
|
|
|
|
// Create action
|
|
$response = $this->call('action.create', [
|
|
'esc_period' => '1h',
|
|
'eventsource' => 0,
|
|
'status' => 0,
|
|
'filter' => [
|
|
'conditions' => [
|
|
[
|
|
'conditiontype' => CONDITION_TYPE_TRIGGER,
|
|
'operator' => CONDITION_OPERATOR_EQUAL,
|
|
'value' => self::$triggerid
|
|
]
|
|
],
|
|
'evaltype' => 0
|
|
],
|
|
'name' => 'Remote command action',
|
|
'operations' => [
|
|
[
|
|
'esc_period' => 0,
|
|
'esc_step_from' => 1,
|
|
'esc_step_to' => 1,
|
|
'operationtype' => OPERATION_TYPE_COMMAND,
|
|
'opcommand' => [
|
|
'scriptid' => self::$scriptid_problem
|
|
],
|
|
'opcommand_hst' => [
|
|
[
|
|
'hostid'=> self::$hostid
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'pause_suppressed' => 0,
|
|
'recovery_operations' => [
|
|
[
|
|
'operationtype' => OPERATION_TYPE_COMMAND,
|
|
'opcommand' => [
|
|
'scriptid' => self::$scriptid_recovery
|
|
],
|
|
'opcommand_hst' => [
|
|
[
|
|
'hostid'=> self::$hostid
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['actionids']));
|
|
$actionid = $response['result']['actionids'];
|
|
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'status' => 1
|
|
]);
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 8);
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_execute()', true, 95, 3);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_AGENT, "Executing command '".self::COMMAND_PROBLEM."'",
|
|
true, 10, 3);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of zbx_process_command_results(), parsed 1',
|
|
true);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_execute()', true, 10, 3);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => $actionid
|
|
], 5, 2);
|
|
$this->assertCount(1, $response['result']);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'In escalation_recover()', true, 200);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_AGENT, "Executing command '".self::COMMAND_RECOVERY."'",
|
|
true, 10, 3);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of zbx_process_command_results(), parsed 1',
|
|
true);
|
|
$this->waitForLogLineToBePresent(self::COMPONENT_SERVER, 'End of escalation_recover()', true);
|
|
|
|
$response = $this->callUntilDataIsPresent('alert.get', [
|
|
'actionids' => $actionid
|
|
], 5, 2);
|
|
$this->assertCount(2, $response['result']);
|
|
}
|
|
|
|
/**
|
|
* @backup actions, alerts, history_uint
|
|
*/
|
|
public function testEscalations_triggerDependency() {
|
|
$this->clearLog(self::COMPONENT_SERVER);
|
|
// Create trigger
|
|
$response = $this->call('trigger.create', [
|
|
'description' => 'Dependent trigger',
|
|
'expression' => 'last(/'.self::HOST_NAME.'/'.self::TRAPPER_ITEM_NAME.')>0',
|
|
'dependencies' => [
|
|
['triggerid' => self::$triggerid]
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('triggerids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['triggerids']));
|
|
$dep_triggerid = $response['result']['triggerids'][0];
|
|
|
|
$response = $this->call('action.update', [
|
|
'actionid' => self::$trigger_actionid,
|
|
'filter' => [
|
|
'conditions' => [
|
|
[
|
|
'conditiontype' => '2',
|
|
'operator' => 0,
|
|
'value' => $dep_triggerid
|
|
]
|
|
],
|
|
'evaltype' => 0
|
|
]
|
|
]);
|
|
$this->assertArrayHasKey('actionids', $response['result']);
|
|
$this->assertEquals(1, count($response['result']['actionids']));
|
|
|
|
$this->reloadConfigurationCache();
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 9);
|
|
|
|
$response = $this->call('alert.get', [
|
|
'actionids' => self::$trigger_actionid
|
|
]);
|
|
$this->assertEmpty($response['result']);
|
|
|
|
$this->sendSenderValue(self::HOST_NAME, self::TRAPPER_ITEM_NAME, 0);
|
|
}
|
|
|
|
}
|