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 = <<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); } }