diff --git a/src/zabbix_server/actions.c b/src/zabbix_server/actions.c deleted file mode 100644 index 45758b0..0000000 --- a/src/zabbix_server/actions.c +++ /dev/null @@ -1,3581 +0,0 @@ -/* -** 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. -**/ - -#include "zbxexpression.h" -#include "server.h" -#include "actions.h" - -#include "operations.h" -#include "zbxregexp.h" -#include "audit/zbxaudit.h" -#include "zbxnum.h" -#include "zbxip.h" -#include "zbxdbwrap.h" -#include "zbx_trigger_constants.h" -#include "zbx_item_constants.h" - -/****************************************************************************** - * * - * Purpose: compare events by objectid * - * * - * Parameters: d1 - [IN] event structure to compare to d2 * - * d2 - [IN] event structure to compare to d1 * - * * - * Return value: 0 - equal * - * not 0 - otherwise * - * * - ******************************************************************************/ -static int compare_events(const void *d1, const void *d2) -{ - const zbx_db_event *p1 = *(const zbx_db_event * const *)d1; - const zbx_db_event *p2 = *(const zbx_db_event * const *)d2; - - ZBX_RETURN_IF_NOT_EQUAL(p1->objectid, p2->objectid); - ZBX_RETURN_IF_NOT_EQUAL(p1->object, p2->object); - - return 0; -} - -/****************************************************************************** - * * - * Purpose: save eventids that match condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * objectid - [IN] object id, for example trigger or item id * - * object - [IN] object, for example EVENT_OBJECT_TRIGGER * - ******************************************************************************/ -static void add_condition_match(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition, - zbx_uint64_t objectid, int object) -{ - int index; - const zbx_db_event event_search = {.objectid = objectid, .object = object}; - - if (FAIL != (index = zbx_vector_ptr_bsearch((const zbx_vector_ptr_t *)esc_events, &event_search, - compare_events))) - { - const zbx_db_event *event = esc_events->values[index]; - int i; - - zbx_vector_uint64_append(&condition->eventids, event->eventid); - - for (i = index - 1; 0 <= i; i--) - { - event = esc_events->values[i]; - - if (event->objectid != objectid || event->object != object) - break; - - zbx_vector_uint64_append(&condition->eventids, event->eventid); - } - - for (i = index + 1; i < esc_events->values_num; i++) - { - event = esc_events->values[i]; - - if (event->objectid != objectid || event->object != object) - break; - - zbx_vector_uint64_append(&condition->eventids, event->eventid); - } - } -} - -/****************************************************************************** - * * - * Purpose: get objectids of escalation events * - * * - * Parameters: esc_events [IN] - events to check * - * objectids [OUT] - event objectids to be used in condition * - * allocation * - * * - ******************************************************************************/ -static void get_object_ids(const zbx_vector_db_event_t *esc_events, zbx_vector_uint64_t *objectids) -{ - zbx_vector_uint64_reserve(objectids, esc_events->values_num); - - for (int i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - zbx_vector_uint64_append(objectids, event->objectid); - } - - zbx_vector_uint64_uniq(objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); -} - -/****************************************************************************** - * * - * Purpose: check host group condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_host_group_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - zbx_vector_uint64_t objectids, groupids; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - zbx_vector_uint64_create(&objectids); - zbx_vector_uint64_create(&groupids); - - get_object_ids(esc_events, &objectids); - zbx_dc_get_nested_hostgroupids(&condition_value, 1, &groupids); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct f.triggerid" - " from hosts_groups hg,hosts h,items i,functions f" - " where hg.hostid=h.hostid" - " and h.hostid=i.hostid" - " and i.itemid=f.itemid" - " and"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", - objectids.values, objectids.values_num); - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and"); - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids.values, groupids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - { - int index; - - if (FAIL != (index = zbx_vector_uint64_search(&objectids, objectid, - ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - { - zbx_vector_uint64_remove_noorder(&objectids, index); - } - } - else - add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER); - - } - zbx_db_free_result(result); - - if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - { - int i; - - for (i = 0; i < objectids.values_num; i++) - add_condition_match(esc_events, condition, objectids.values[i], EVENT_OBJECT_TRIGGER); - } - - zbx_vector_uint64_destroy(&groupids); - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: mapping between discovered triggers and their prototypes * - * * - * Parameters: sql [IN/OUT] - allocated sql query * - * sql_alloc [IN/OUT] - how much bytes allocated * - * objectids_tmp [IN/OUT] - uses to allocate query * - * * - * * - ******************************************************************************/ -static void trigger_parents_sql_alloc(char **sql, size_t *sql_alloc, zbx_vector_uint64_t *objectids_tmp) -{ - size_t sql_offset = 0; - - zbx_snprintf_alloc(sql, sql_alloc, &sql_offset, - "select triggerid,parent_triggerid" - " from trigger_discovery" - " where"); - - zbx_db_add_condition_alloc(sql, sql_alloc, &sql_offset, "triggerid", objectids_tmp->values, - objectids_tmp->values_num); -} - -/****************************************************************************** - * * - * Purpose: copy objects to pair, for hierarchy checks * - * * - * Parameters: objectids [IN] - objects * - * objectids_pair [OUT] - objectids will be copied here * - * * - ******************************************************************************/ -static void objectids_to_pair(zbx_vector_uint64_t *objectids, zbx_vector_uint64_pair_t *objectids_pair) -{ - int i; - - zbx_vector_uint64_pair_reserve(objectids_pair, objectids->values_num); - - for (i = 0; i < objectids->values_num; i++) - { - zbx_uint64_pair_t pair = {objectids->values[i], objectids->values[i]}; - - zbx_vector_uint64_pair_append(objectids_pair, pair); - } -} - -/****************************************************************************** - * * - * Purpose: there can be multiple levels of templates, that need * - * resolving in order to compare to condition * - * * - * Parameters: object - [IN] type of the object that generated event * - * Parameters: esc_events - [IN] events being checked * - * objectids - [IN] object ids of the esc_events * - * (contents can be changed by processing * - * and should not be used by caller) * - * objectids_pair - [IN] pairs of (objectid, source objectid) * - * where objectid are ids of the esc_events* - * and source objectid is object id for * - * normal objects and prototype id for * - * discovered objects * - * (contents can be changed by processing * - * and should not be used by caller) * - * condition - [IN/OUT] condition to evaluate, matched * - * events will be added to condition * - * eventids vector * - * condition_value - [IN] condition value for matching * - * sql_str - [IN] custom sql query, must obtain object, * - * template object id and value * - * sql_field - [IN] field name that is added to the sql * - * query condition * - * * - ******************************************************************************/ -static void check_object_hierarchy(int object, const zbx_vector_db_event_t *esc_events, - zbx_vector_uint64_t *objectids, zbx_vector_uint64_pair_t *objectids_pair, zbx_condition_t *condition, - zbx_uint64_t condition_value, const char *sql_str, const char *sql_field) -{ - int i; - zbx_vector_uint64_t objectids_tmp; - zbx_vector_uint64_pair_t objectids_pair_tmp; - char *sql = NULL; - size_t sql_alloc = 0; - - zbx_vector_uint64_pair_create(&objectids_pair_tmp); - zbx_vector_uint64_create(&objectids_tmp); - zbx_vector_uint64_reserve(&objectids_tmp, objectids_pair->values_num); - - while (0 != objectids_pair->values_num) - { - zbx_db_result_t result; - zbx_db_row_t row; - size_t sql_offset = 0; - - /* objectids that need parents to be determined */ - for (i = 0; i < objectids_pair->values_num; i++) - zbx_vector_uint64_append(&objectids_tmp, objectids_pair->values[i].second); - - zbx_vector_uint64_sort(&objectids_tmp, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - /* multiple hosts can share trigger from same template, don't allocate duplicate ids */ - zbx_vector_uint64_uniq(&objectids_tmp, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, sql_str); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, sql_field, objectids_tmp.values, - objectids_tmp.values_num); - - zbx_vector_uint64_clear(&objectids_tmp); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid, parent_objectid, value; - - ZBX_STR2UINT64(objectid, row[0]); - ZBX_STR2UINT64(parent_objectid, row[1]); - ZBX_STR2UINT64(value, row[2]); - - /* find all templates or trigger ids that match our condition and get original id */ - for (i = 0; i < objectids_pair->values_num; i++) - { - /* objectid is id that has template id, that match condition */ - /* second are those that we did select on */ - if (objectids_pair->values[i].second != objectid) - continue; - - if (value == condition_value) - { - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op) - { - int j; - - /* remove equals from result set, leaving only not equals */ - if (FAIL != (j = zbx_vector_uint64_search(objectids, - objectids_pair->values[i].first, - ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - { - zbx_vector_uint64_remove_noorder(objectids, j); - } - } - else - { - add_condition_match(esc_events, condition, - objectids_pair->values[i].first, object); - } - } - else - { - /* update template id to next level, to compare to condition in next select */ - - objectids_pair->values[i].second = parent_objectid; - zbx_vector_uint64_pair_append(&objectids_pair_tmp, objectids_pair->values[i]); - } - - objectids_pair->values[i].second = 0; - } - } - zbx_free(sql); - zbx_db_free_result(result); - - /* resolve in next select only those triggerids that have template id and not equal to condition */ - zbx_vector_uint64_pair_clear(objectids_pair); - - if (0 != objectids_pair_tmp.values_num) - { - zbx_vector_uint64_pair_append_array(objectids_pair, objectids_pair_tmp.values, - objectids_pair_tmp.values_num); - } - - zbx_vector_uint64_pair_clear(&objectids_pair_tmp); - } - - /* equals are deleted so copy to result those that are left (not equals) */ - if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - { - for (i = 0; i < objectids->values_num; i++) - add_condition_match(esc_events, condition, objectids->values[i], object); - } - - zbx_vector_uint64_pair_destroy(&objectids_pair_tmp); - zbx_vector_uint64_destroy(&objectids_tmp); -} - -/****************************************************************************** - * * - * Purpose: check host template condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_host_template_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0; - zbx_db_result_t result; - zbx_db_row_t row; - zbx_uint64_t condition_value; - zbx_vector_uint64_t objectids; - zbx_vector_uint64_pair_t objectids_pair; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - zbx_vector_uint64_create(&objectids); - zbx_vector_uint64_pair_create(&objectids_pair); - - get_object_ids(esc_events, &objectids); - objectids_to_pair(&objectids, &objectids_pair); - - ZBX_STR2UINT64(condition_value, condition->value); - - trigger_parents_sql_alloc(&sql, &sql_alloc, &objectids); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_pair_t pair; - int i; - - ZBX_STR2UINT64(pair.first, row[0]); - - if (FAIL != (i = zbx_vector_uint64_pair_search(&objectids_pair, pair, ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - ZBX_STR2UINT64(objectids_pair.values[i].second, row[1]); - } - zbx_db_free_result(result); - - check_object_hierarchy(EVENT_OBJECT_TRIGGER, esc_events, &objectids, &objectids_pair, condition, condition_value, - "select distinct t.triggerid,t.templateid,i.hostid" - " from items i,functions f,triggers t" - " where i.itemid=f.itemid" - " and f.triggerid=t.templateid" - " and", - "t.triggerid"); - - zbx_vector_uint64_destroy(&objectids); - zbx_vector_uint64_pair_destroy(&objectids_pair); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check host condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_host_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - const char *operation; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - zbx_vector_uint64_t objectids; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) - operation = " and"; - else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - operation = " and not"; - else - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - zbx_vector_uint64_create(&objectids); - - get_object_ids(esc_events, &objectids); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct f.triggerid" - " from items i,functions f" - " where i.itemid=f.itemid" - "%s i.hostid=" ZBX_FS_UI64 - " and", - operation, - condition_value); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", objectids.values, objectids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER); - } - zbx_db_free_result(result); - - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check trigger id condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_trigger_id_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - zbx_uint64_t condition_value; - zbx_vector_uint64_t objectids; - zbx_vector_uint64_pair_t objectids_pair; - int i; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - zbx_vector_uint64_create(&objectids); - zbx_vector_uint64_pair_create(&objectids_pair); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (event->objectid == condition_value) - { - if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - } - else - zbx_vector_uint64_append(&objectids, event->objectid); - } - - if (0 != objectids.values_num) - { - zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - objectids_to_pair(&objectids, &objectids_pair); - - check_object_hierarchy(EVENT_OBJECT_TRIGGER, esc_events, &objectids, &objectids_pair, condition, condition_value, - "select triggerid,templateid,templateid" - " from triggers" - " where templateid is not null and", - "triggerid"); - } - - zbx_vector_uint64_destroy(&objectids); - zbx_vector_uint64_pair_destroy(&objectids_pair); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check trigger name condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_trigger_name_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int i; - - if (ZBX_CONDITION_OPERATOR_LIKE != condition->op && ZBX_CONDITION_OPERATOR_NOT_LIKE != condition->op) - return NOTSUPPORTED; - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_LIKE: - if (NULL != strstr(event->name, condition->value)) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case ZBX_CONDITION_OPERATOR_NOT_LIKE: - if (NULL == strstr(event->name, condition->value)) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - } - } - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check trigger severity condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_trigger_severity_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - unsigned char condition_value; - int i; - - condition_value = (unsigned char)atoi(condition->value); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - if (event->trigger.priority == condition_value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - if (event->trigger.priority != condition_value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case ZBX_CONDITION_OPERATOR_MORE_EQUAL: - if (event->trigger.priority >= condition_value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case ZBX_CONDITION_OPERATOR_LESS_EQUAL: - if (event->trigger.priority <= condition_value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - default: - return NOTSUPPORTED; - } - } - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check time period condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_time_period_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *period; - int i; - - if (ZBX_CONDITION_OPERATOR_IN != condition->op && ZBX_CONDITION_OPERATOR_NOT_IN != condition->op) - return NOTSUPPORTED; - - period = zbx_strdup(NULL, condition->value); - zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &period, - ZBX_MACRO_TYPE_COMMON, NULL, 0); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - int res; - - if (SUCCEED == zbx_check_time_period(period, (time_t)event->clock, NULL, &res)) - { - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_IN: - if (SUCCEED == res) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case ZBX_CONDITION_OPERATOR_NOT_IN: - if (FAIL == res) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - } - } - else - { - zabbix_log(LOG_LEVEL_WARNING, "Invalid time period \"%s\" for condition id [" ZBX_FS_UI64 "]", - period, condition->conditionid); - } - } - - zbx_free(period); - - return SUCCEED; -} - -static int check_suppressed_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int i; - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_YES: - if (ZBX_PROBLEM_SUPPRESSED_TRUE == event->suppressed) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case ZBX_CONDITION_OPERATOR_NO: - if (ZBX_PROBLEM_SUPPRESSED_FALSE == event->suppressed) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - default: - return NOTSUPPORTED; - } - } - - return SUCCEED; -} - -static int check_acknowledged_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int i; - zbx_vector_uint64_t eventids; - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - int ret = SUCCEED; - - zbx_vector_uint64_create(&eventids); - zbx_vector_uint64_reserve(&eventids, esc_events->values_num); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - zbx_vector_uint64_append(&eventids, event->eventid); - } - - zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select eventid" - " from events" - " where acknowledged=%d" - " and", - atoi(condition->value)); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "eventid", eventids.values, eventids.values_num); - - result = zbx_db_select("%s", sql); - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t eventid; - - ZBX_STR2UINT64(eventid, row[0]); - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - zbx_vector_uint64_append(&condition->eventids, eventid); - break; - default: - ret = NOTSUPPORTED; - } - - } - zbx_db_free_result(result); - zbx_free(sql); - - zbx_vector_uint64_destroy(&eventids); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: check condition event tag * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - ******************************************************************************/ -static void check_condition_event_tag(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int i, ret, ret_continue; - - if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op || ZBX_CONDITION_OPERATOR_NOT_LIKE == condition->op) - ret_continue = SUCCEED; - else - ret_continue = FAIL; - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - int j; - - ret = ret_continue; - - for (j = 0; j < event->tags.values_num && ret == ret_continue; j++) - { - const zbx_tag_t *tag = event->tags.values[j]; - - ret = zbx_strmatch_condition(tag->tag, condition->value, condition->op); - } - - if (SUCCEED == ret) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - } -} - -/****************************************************************************** - * * - * Purpose: check condition event tag value * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - ******************************************************************************/ -static void check_condition_event_tag_value(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int i, ret, ret_continue; - - if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op || ZBX_CONDITION_OPERATOR_NOT_LIKE == condition->op) - ret_continue = SUCCEED; - else - ret_continue = FAIL; - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - int j; - - ret = ret_continue; - - for (j = 0; j < event->tags.values_num && ret == ret_continue; j++) - { - zbx_tag_t *tag = event->tags.values[j]; - - if (0 == strcmp(condition->value2, tag->tag)) - ret = zbx_strmatch_condition(tag->value, condition->value, condition->op); - } - - if (SUCCEED == ret) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - } -} - -/****************************************************************************** - * * - * Purpose: check if event matches single condition * - * * - * Parameters: event - trigger event to check * - * (event->source == EVENT_SOURCE_TRIGGERS) * - * condition - condition for matching * - * * - * Return value: SUCCEED - matches, FAIL - otherwise * - * * - ******************************************************************************/ -static void check_trigger_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int ret; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - switch (condition->conditiontype) - { - case ZBX_CONDITION_TYPE_HOST_GROUP: - ret = check_host_group_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_HOST_TEMPLATE: - ret = check_host_template_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_HOST: - ret = check_host_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_TRIGGER: - ret = check_trigger_id_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_TRIGGER_NAME: - ret = check_trigger_name_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_TRIGGER_SEVERITY: - ret = check_trigger_severity_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_TIME_PERIOD: - ret = check_time_period_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_SUPPRESSED: - ret = check_suppressed_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_EVENT_ACKNOWLEDGED: - ret = check_acknowledged_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_EVENT_TAG: - check_condition_event_tag(esc_events, condition); - ret = SUCCEED; - break; - case ZBX_CONDITION_TYPE_EVENT_TAG_VALUE: - check_condition_event_tag_value(esc_events,condition); - ret = SUCCEED; - break; - default: - zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->conditiontype, condition->conditionid); - ret = FAIL; - } - - if (NOTSUPPORTED == ret) - { - zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->op, condition->conditionid); - } - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); -} - -/****************************************************************************** - * * - * Purpose: get objectids for dhost * - * * - * Parameters: esc_events - [IN] events to check * - * objectids - [OUT] event objectids to be used in condition * - * allocation 2 vectors where first one is * - * dhost ids, second is dservice * -* * - ******************************************************************************/ -static void get_object_ids_discovery(const zbx_vector_db_event_t *esc_events, zbx_vector_uint64_t *objectids) -{ - int i; - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (event->object == EVENT_OBJECT_DHOST) - zbx_vector_uint64_append(&objectids[0], event->objectid); - else - zbx_vector_uint64_append(&objectids[1], event->objectid); - } - - zbx_vector_uint64_uniq(&objectids[0], ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(&objectids[1], ZBX_DEFAULT_UINT64_COMPARE_FUNC); -} -/****************************************************************************** - * * - * Purpose: check discovery rule condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_drule_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - const char *operation_and, *operation_where; - size_t sql_alloc = 0, i; - zbx_db_result_t result; - zbx_db_row_t row; - int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE}; - zbx_vector_uint64_t objectids[2]; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) - { - operation_and = " and"; - operation_where = " where"; - } - else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - { - operation_and = " and not"; - operation_where = " where not"; - } - else - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - zbx_vector_uint64_create(&objectids[0]); - zbx_vector_uint64_create(&objectids[1]); - - get_object_ids_discovery(esc_events, objectids); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - size_t sql_offset = 0; - - if (0 == objectids[i].values_num) - continue; - - if (EVENT_OBJECT_DHOST == objects[i]) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select dhostid" - " from dhosts" - "%s druleid=" ZBX_FS_UI64 - " and", - operation_where, - condition_value); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid", - objectids[i].values, objectids[i].values_num); - } - else /* EVENT_OBJECT_DSERVICE */ - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select s.dserviceid" - " from dhosts h,dservices s" - " where h.dhostid=s.dhostid" - "%s h.druleid=" ZBX_FS_UI64 - " and", - operation_and, - condition_value); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid", - objectids[i].values, objectids[i].values_num); - } - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - add_condition_match(esc_events, condition, objectid, objects[i]); - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids[0]); - zbx_vector_uint64_destroy(&objectids[1]); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check discovery check condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_dcheck_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - const char *operation_where; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - int object = EVENT_OBJECT_DSERVICE, i; - zbx_vector_uint64_t objectids; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) - operation_where = " where"; - else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - operation_where = " where not"; - else - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - zbx_vector_uint64_create(&objectids); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (object == event->object) - zbx_vector_uint64_append(&objectids, event->objectid); - } - - if (0 != objectids.values_num) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select dserviceid" - " from dservices" - "%s dcheckid=" ZBX_FS_UI64 - " and", - operation_where, - condition_value); - - zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values, - objectids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - add_condition_match(esc_events, condition, objectid, object); - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check discovery object condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_dobject_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int i, condition_value_i = atoi(condition->value); - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op) - return NOTSUPPORTED; - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (event->object == condition_value_i) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - } - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check proxy condition for discovery event * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_proxy_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - const char *operation_and; - size_t sql_alloc = 0, i; - zbx_db_result_t result; - zbx_db_row_t row; - int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE}; - zbx_vector_uint64_t objectids[2]; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) - operation_and = " and"; - else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - operation_and = " and not"; - else - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - zbx_vector_uint64_create(&objectids[0]); - zbx_vector_uint64_create(&objectids[1]); - - get_object_ids_discovery(esc_events, objectids); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - size_t sql_offset = 0; - - if (0 == objectids[i].values_num) - continue; - - if (EVENT_OBJECT_DHOST == objects[i]) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select h.dhostid" - " from drules r,dhosts h" - " where r.druleid=h.druleid" - "%s r.proxyid=" ZBX_FS_UI64 - " and", - operation_and, - condition_value); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "h.dhostid", objectids[i].values, - objectids[i].values_num); - } - else /* EVENT_OBJECT_DSERVICE */ - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select s.dserviceid" - " from drules r,dhosts h,dservices s" - " where r.druleid=h.druleid" - " and h.dhostid=s.dhostid" - "%s r.proxyid=" ZBX_FS_UI64 - " and", - operation_and, - condition_value); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid", - objectids[i].values, objectids[i].values_num); - } - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - add_condition_match(esc_events, condition, objectid, objects[i]); - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids[0]); - zbx_vector_uint64_destroy(&objectids[1]); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check discovery value condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_dvalue_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - int object = EVENT_OBJECT_DSERVICE; - zbx_vector_uint64_t objectids; - int i; - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - case ZBX_CONDITION_OPERATOR_MORE_EQUAL: - case ZBX_CONDITION_OPERATOR_LESS_EQUAL: - case ZBX_CONDITION_OPERATOR_LIKE: - case ZBX_CONDITION_OPERATOR_NOT_LIKE: - break; - default: - return NOTSUPPORTED; - } - - zbx_vector_uint64_create(&objectids); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (object == event->object) - zbx_vector_uint64_append(&objectids, event->objectid); - } - - if (0 != objectids.values_num) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select dserviceid,value" - " from dservices" - " where"); - - zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values, - objectids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - if (0 == strcmp(condition->value, row[1])) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - if (0 != strcmp(condition->value, row[1])) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_MORE_EQUAL: - if (0 <= strcmp(row[1], condition->value)) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_LESS_EQUAL: - if (0 >= strcmp(row[1], condition->value)) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_LIKE: - if (NULL != strstr(row[1], condition->value)) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_NOT_LIKE: - if (NULL == strstr(row[1], condition->value)) - add_condition_match(esc_events, condition, objectid, object); - break; - } - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check host ip condition for discovery event * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_dhost_ip_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, i; - zbx_db_result_t result; - zbx_db_row_t row; - int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE}; - zbx_vector_uint64_t objectids[2]; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - zbx_vector_uint64_create(&objectids[0]); - zbx_vector_uint64_create(&objectids[1]); - - get_object_ids_discovery(esc_events, objectids); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - size_t sql_offset = 0; - - if (0 == objectids[i].values_num) - continue; - - if (EVENT_OBJECT_DHOST == objects[i]) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct dhostid,ip" - " from dservices" - " where"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid", objectids[i].values, - objectids[i].values_num); - } - else /* EVENT_OBJECT_DSERVICE */ - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct dserviceid,ip" - " from dservices" - " where"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", - objectids[i].values, objectids[i].values_num); - } - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - if (SUCCEED == zbx_ip_in_list(condition->value, row[1])) - add_condition_match(esc_events, condition, objectid, objects[i]); - break; - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - if (SUCCEED != zbx_ip_in_list(condition->value, row[1])) - add_condition_match(esc_events, condition, objectid, objects[i]); - break; - } - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids[0]); - zbx_vector_uint64_destroy(&objectids[1]); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check service type condition for discovery event * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_dservice_type_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - int object = EVENT_OBJECT_DSERVICE; - zbx_vector_uint64_t objectids; - int i, condition_value_i; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - condition_value_i = atoi(condition->value); - - zbx_vector_uint64_create(&objectids); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (object == event->object) - zbx_vector_uint64_append(&objectids, event->objectid); - } - - if (0 != objectids.values_num) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select ds.dserviceid,dc.type" - " from dservices ds,dchecks dc" - " where ds.dcheckid=dc.dcheckid" - " and"); - - zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "ds.dserviceid", objectids.values, - objectids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - int tmp_int; - - ZBX_STR2UINT64(objectid, row[0]); - tmp_int = atoi(row[1]); - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - if (condition_value_i == tmp_int) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - if (condition_value_i != tmp_int) - add_condition_match(esc_events, condition, objectid, object); - break; - } - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check discovery status condition * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_dstatus_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int i, condition_value_i = atoi(condition->value); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - if (condition_value_i == event->value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - if (condition_value_i != event->value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - default: - return NOTSUPPORTED; - } - } - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check uptime condition for discovery * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_duptime_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, i; - zbx_db_result_t result; - zbx_db_row_t row; - int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE}; - zbx_vector_uint64_t objectids[2]; - int condition_value_i; - - if (ZBX_CONDITION_OPERATOR_LESS_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_MORE_EQUAL != condition->op) - return NOTSUPPORTED; - - condition_value_i = atoi(condition->value); - - zbx_vector_uint64_create(&objectids[0]); - zbx_vector_uint64_create(&objectids[1]); - - get_object_ids_discovery(esc_events, objectids); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - size_t sql_offset = 0; - - if (0 == objectids[i].values_num) - continue; - - if (EVENT_OBJECT_DHOST == objects[i]) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select dhostid,status,lastup,lastdown" - " from dhosts" - " where"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid", - objectids[i].values, objectids[i].values_num); - } - else /* EVENT_OBJECT_DSERVICE */ - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select dserviceid,status,lastup,lastdown" - " from dservices" - " where"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", - objectids[i].values, objectids[i].values_num); - } - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - int now, tmp_int; - - ZBX_STR2UINT64(objectid, row[0]); - - now = time(NULL); - tmp_int = DOBJECT_STATUS_UP == atoi(row[1]) ? atoi(row[2]) : atoi(row[3]); - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_LESS_EQUAL: - if (0 != tmp_int && (now - tmp_int) <= condition_value_i) - add_condition_match(esc_events, condition, objectid, objects[i]); - break; - case ZBX_CONDITION_OPERATOR_MORE_EQUAL: - if (0 != tmp_int && (now - tmp_int) >= condition_value_i) - add_condition_match(esc_events, condition, objectid, objects[i]); - break; - } - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids[0]); - zbx_vector_uint64_destroy(&objectids[1]); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check service port condition for discovery * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_dservice_port_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - int object = EVENT_OBJECT_DSERVICE; - zbx_vector_uint64_t objectids; - int i; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - zbx_vector_uint64_create(&objectids); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (object == event->object) - zbx_vector_uint64_append(&objectids, event->objectid); - } - - if (0 != objectids.values_num) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select dserviceid,port" - " from dservices" - " where"); - - zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values, - objectids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - if (SUCCEED == zbx_int_in_list(condition->value, atoi(row[1]))) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - if (SUCCEED != zbx_int_in_list(condition->value, atoi(row[1]))) - add_condition_match(esc_events, condition, objectid, object); - break; - } - } - zbx_db_free_result(result); - } - - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check if event matches single condition * - * * - * Parameters: event - discovery event to check * - * (event->source == EVENT_SOURCE_DISCOVERY) * - * condition - condition for matching * - * * - * Return value: SUCCEED - matches, FAIL - otherwise * - * * - ******************************************************************************/ -static void check_discovery_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int ret; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - switch (condition->conditiontype) - { - case ZBX_CONDITION_TYPE_DRULE: - ret = check_drule_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DCHECK: - ret = check_dcheck_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DOBJECT: - ret = check_dobject_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_PROXY: - ret = check_proxy_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DVALUE: - ret = check_dvalue_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DHOST_IP: - ret = check_dhost_ip_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DSERVICE_TYPE: - ret = check_dservice_type_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DSTATUS: - ret = check_dstatus_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DUPTIME: - ret = check_duptime_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_DSERVICE_PORT: - ret = check_dservice_port_condition(esc_events, condition); - break; - default: - ret = FAIL; - zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->conditiontype, condition->conditionid); - } - - if (NOTSUPPORTED == ret) - { - zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->op, condition->conditionid); - } - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); -} - -/****************************************************************************** - * * - * Purpose: check metadata or host condition for auto registration * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_hostname_metadata_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - int object = EVENT_OBJECT_ZABBIX_ACTIVE; - zbx_vector_uint64_t objectids; - const char *condition_field; - - switch(condition->op) - { - case ZBX_CONDITION_OPERATOR_LIKE: - case ZBX_CONDITION_OPERATOR_NOT_LIKE: - case ZBX_CONDITION_OPERATOR_REGEXP: - case ZBX_CONDITION_OPERATOR_NOT_REGEXP: - break; - default: - return NOTSUPPORTED; - } - - if (ZBX_CONDITION_TYPE_HOST_NAME == condition->conditiontype) - condition_field = "host"; - else - condition_field = "host_metadata"; - - zbx_vector_uint64_create(&objectids); - get_object_ids(esc_events, &objectids); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select autoreg_hostid,%s" - " from autoreg_host" - " where", - condition_field); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid", objectids.values, objectids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_LIKE: - if (NULL != strstr(row[1], condition->value)) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_NOT_LIKE: - if (NULL == strstr(row[1], condition->value)) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_REGEXP: - if (NULL != zbx_regexp_match(row[1], condition->value, NULL)) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_NOT_REGEXP: - if (NULL == zbx_regexp_match(row[1], condition->value, NULL)) - add_condition_match(esc_events, condition, objectid, object); - break; - } - } - zbx_db_free_result(result); - - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check proxy condition for auto registration * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_areg_proxy_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_db_result_t result; - zbx_db_row_t row; - int object = EVENT_OBJECT_ZABBIX_ACTIVE; - zbx_vector_uint64_t objectids; - zbx_uint64_t condition_value; - - ZBX_STR2UINT64(condition_value, condition->value); - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - zbx_vector_uint64_create(&objectids); - get_object_ids(esc_events, &objectids); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select autoreg_hostid,proxyid" - " from autoreg_host" - " where"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid", - objectids.values, objectids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t id; - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - ZBX_DBROW2UINT64(id, row[1]); - - switch (condition->op) - { - case ZBX_CONDITION_OPERATOR_EQUAL: - if (id == condition_value) - add_condition_match(esc_events, condition, objectid, object); - break; - case ZBX_CONDITION_OPERATOR_NOT_EQUAL: - if (id != condition_value) - add_condition_match(esc_events, condition, objectid, object); - break; - } - } - zbx_db_free_result(result); - - zbx_vector_uint64_destroy(&objectids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check if event matches single condition * - * * - * Parameters: event - autoregistration event to check * - * (event->source == EVENT_SOURCE_AUTOREGISTRATION) * - * condition - condition for matching * - * * - * Return value: SUCCEED - matches, FAIL - otherwise * - * * - ******************************************************************************/ -static void check_autoregistration_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - const char *__function_name = "check_auto_registration_condition"; - int ret; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); - - switch (condition->conditiontype) - { - case ZBX_CONDITION_TYPE_HOST_NAME: - case ZBX_CONDITION_TYPE_HOST_METADATA: - ret = check_hostname_metadata_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_PROXY: - ret = check_areg_proxy_condition(esc_events, condition); - break; - default: - zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->conditiontype, condition->conditionid); - ret = FAIL; - } - - if (NOTSUPPORTED == ret) - { - zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->op, condition->conditionid); - } - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); -} - -/****************************************************************************** - * * - * Purpose: not all event objects are supported for internal events * - * * - * Parameters: events - [IN] events to check * - * * - * Return value: SUCCEED - supported * - * FAIL - not supported * - * * - ******************************************************************************/ -static int is_supported_event_object(const zbx_db_event *event) -{ - return (EVENT_OBJECT_TRIGGER == event->object || EVENT_OBJECT_ITEM == event->object || - EVENT_OBJECT_LLDRULE == event->object) ? SUCCEED : FAIL; -} - -/****************************************************************************** - * * - * Purpose: check event type condition for internal events * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_intern_event_type_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ -/* event type action condition values */ -/* SYNC WITH PHP! */ -#define EVENT_TYPE_ITEM_NOTSUPPORTED 0 -/* #define EVENT_TYPE_ITEM_NORMAL 1 deprecated */ -#define EVENT_TYPE_LLDRULE_NOTSUPPORTED 2 -/* #define EVENT_TYPE_LLDRULE_NORMAL 3 deprecated */ -#define EVENT_TYPE_TRIGGER_UNKNOWN 4 -/* #define EVENT_TYPE_TRIGGER_NORMAL 5 deprecated */ - int i; - zbx_uint64_t condition_value; - - condition_value = atoi(condition->value); - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - if (FAIL == is_supported_event_object(event)) - { - zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d] for condition id [" ZBX_FS_UI64 "]", - event->object, condition->conditionid); - continue; - } - - switch (condition_value) - { - case EVENT_TYPE_ITEM_NOTSUPPORTED: - if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NOTSUPPORTED == event->value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case EVENT_TYPE_TRIGGER_UNKNOWN: - if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_UNKNOWN == event->value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - case EVENT_TYPE_LLDRULE_NOTSUPPORTED: - if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NOTSUPPORTED == event->value) - zbx_vector_uint64_append(&condition->eventids, event->eventid); - break; - default: - return NOTSUPPORTED; - } - } - - return SUCCEED; -#undef EVENT_TYPE_ITEM_NOTSUPPORTED -#undef EVENT_TYPE_LLDRULE_NOTSUPPORTED -#undef EVENT_TYPE_TRIGGER_UNKNOWN -} - -/****************************************************************************** - * * - * Purpose: get objectids of escalation internal events * - * * - * Parameters: esc_events - [IN] events to check * - * objectids - [OUT] event objectids to be used in condition * - * allocation 2 vectors where first one is * - * trigger object ids, second is rest * - * objects - [IN] the array of event objects * - * objects_num - [IN] the number of objects in objects array * - * * - ******************************************************************************/ -static void get_object_ids_internal(const zbx_vector_db_event_t *esc_events, zbx_vector_uint64_t *objectids, - const int *objects, const int objects_num) -{ - int i, j; - - for (i = 0; i < esc_events->values_num; i++) - { - const zbx_db_event *event = esc_events->values[i]; - - for (j = 0; j < objects_num; j++) - { - if (event->object == objects[j]) - { - zbx_vector_uint64_append(&objectids[j], event->objectid); - break; - } - } - - if (j == objects_num) - zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d]", event->object); - } - - for (i = 0; i < objects_num; i++) - zbx_vector_uint64_uniq(&objectids[i], ZBX_DEFAULT_UINT64_COMPARE_FUNC); -} - -/****************************************************************************** - * * - * Purpose: check host group condition for internal events * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_intern_host_group_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0, i; - zbx_db_result_t result; - zbx_db_row_t row; - int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE}; - zbx_vector_uint64_t objectids[3], groupids; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - zbx_vector_uint64_create(&objectids[i]); - - zbx_vector_uint64_create(&groupids); - - get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects)); - - zbx_dc_get_nested_hostgroupids(&condition_value, 1, &groupids); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - size_t sql_offset = 0; - - if (0 == objectids[i].values_num) - continue; - - if (EVENT_OBJECT_TRIGGER == objects[i]) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct f.triggerid" - " from hosts_groups hg,hosts h,items i,functions f" - " where hg.hostid=h.hostid" - " and h.hostid=i.hostid" - " and i.itemid=f.itemid" - " and"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", objectids[i].values, - objectids[i].values_num); - } - else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */ - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct i.itemid" - " from hosts_groups hg,hosts h,items i" - " where hg.hostid=h.hostid" - " and h.hostid=i.hostid" - " and"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid", - objectids[i].values, objectids[i].values_num); - } - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and"); - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids.values, - groupids.values_num); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - { - int index; - - if (FAIL != (index = zbx_vector_uint64_search(&objectids[i], objectid, - ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - { - zbx_vector_uint64_remove_noorder(&objectids[i], index); - } - } - else - add_condition_match(esc_events, condition, objectid, objects[i]); - } - zbx_db_free_result(result); - } - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - { - int j; - - for (j = 0; j < objectids[i].values_num; j++) - add_condition_match(esc_events, condition, objectids[i].values[j], objects[i]); - } - - zbx_vector_uint64_destroy(&objectids[i]); - } - - zbx_vector_uint64_destroy(&groupids); - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: get parent id from item discovery * - * * - * Parameters: sql [IN/OUT] - allocated sql query * - * sql_alloc [IN/OUT] - how much bytes allocated * - * objectids_tmp [IN/OUT] - uses to allocate query, removes * - * duplicates * - * * - ******************************************************************************/ -static void item_parents_sql_alloc(char **sql, size_t *sql_alloc, zbx_vector_uint64_t *objectids_tmp) -{ - size_t sql_offset = 0; - - zbx_snprintf_alloc(sql, sql_alloc, &sql_offset, - "select i.itemid,id.parent_itemid" - " from item_discovery id,items i" - " where id.itemid=i.itemid" - " and i.flags=%d" - " and", - ZBX_FLAG_DISCOVERY_CREATED); - - zbx_db_add_condition_alloc(sql, sql_alloc, &sql_offset, "i.itemid", - objectids_tmp->values, objectids_tmp->values_num); -} - -/****************************************************************************** - * * - * Purpose: check host template condition for internal events * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_intern_host_template_condition(const zbx_vector_db_event_t *esc_events, - zbx_condition_t *condition) -{ - char *sql = NULL; - size_t sql_alloc = 0; - zbx_db_result_t result; - zbx_db_row_t row; - zbx_uint64_t condition_value; - int i, j; - int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE}; - zbx_vector_uint64_t objectids[3]; - zbx_vector_uint64_pair_t objectids_pair[3]; - - if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) - return NOTSUPPORTED; - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - zbx_vector_uint64_create(&objectids[i]); - zbx_vector_uint64_pair_create(&objectids_pair[i]); - } - - get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects)); - - ZBX_STR2UINT64(condition_value, condition->value); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - zbx_vector_uint64_t *objectids_ptr = &objectids[i]; - zbx_vector_uint64_pair_t *objectids_pair_ptr = &objectids_pair[i]; - - if (0 == objectids_ptr->values_num) - continue; - - objectids_to_pair(objectids_ptr, objectids_pair_ptr); - - if (EVENT_OBJECT_TRIGGER == objects[i]) - trigger_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr); - else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */ - item_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr); - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_pair_t pair; - - ZBX_STR2UINT64(pair.first, row[0]); - - if (FAIL != (j = zbx_vector_uint64_pair_search(objectids_pair_ptr, pair, - ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - { - ZBX_STR2UINT64(objectids_pair_ptr->values[j].second, row[1]); - } - } - zbx_db_free_result(result); - - check_object_hierarchy(objects[i], esc_events, objectids_ptr, objectids_pair_ptr, condition, condition_value, - 0 == i ? - "select distinct t.triggerid,t.templateid,i.hostid" - " from items i,functions f,triggers t" - " where i.itemid=f.itemid" - " and f.triggerid=t.templateid" - " and" : - "select distinct h.itemid,t.itemid,t.hostid" - " from items t,items h" - " where t.itemid=h.templateid" - " and", - 0 == i ? "t.triggerid" : "h.itemid"); - } - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - zbx_vector_uint64_destroy(&objectids[i]); - zbx_vector_uint64_pair_destroy(&objectids_pair[i]); - } - - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check host condition for internal events * - * * - * Parameters: esc_events - [IN] events to check * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - * Return value: SUCCEED - supported operator * - * NOTSUPPORTED - not supported operator * - * * - ******************************************************************************/ -static int check_intern_host_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - char *sql = NULL; - const char *operation, *operation_item; - size_t sql_alloc = 0, i; - zbx_db_result_t result; - zbx_db_row_t row; - int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE}; - zbx_vector_uint64_t objectids[3]; - zbx_uint64_t condition_value; - - if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) - { - operation = " and"; - operation_item = " where"; - } - else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) - { - operation = " and not"; - operation_item = " where not"; - } - else - return NOTSUPPORTED; - - ZBX_STR2UINT64(condition_value, condition->value); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - zbx_vector_uint64_create(&objectids[i]); - - get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects)); - - for (i = 0; i < (int)ARRSIZE(objects); i++) - { - size_t sql_offset = 0; - - if (0 == objectids[i].values_num) - continue; - - if (EVENT_OBJECT_TRIGGER == objects[i]) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct f.triggerid" - " from items i,functions f" - " where i.itemid=f.itemid" - "%s i.hostid=" ZBX_FS_UI64 - " and", - operation, - condition_value); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", - objectids[i].values, objectids[i].values_num); - } - else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */ - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "select itemid" - " from items" - "%s hostid=" ZBX_FS_UI64 - " and", - operation_item, - condition_value); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", - objectids[i].values, objectids[i].values_num); - } - - result = zbx_db_select("%s", sql); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t objectid; - - ZBX_STR2UINT64(objectid, row[0]); - add_condition_match(esc_events, condition, objectid, objects[i]); - } - zbx_db_free_result(result); - } - - for (i = 0; i < (int)ARRSIZE(objects); i++) - zbx_vector_uint64_destroy(&objectids[i]); - - zbx_free(sql); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: check if internal event matches single condition * - * * - * Parameters: event - [IN] trigger event to check * - * condition - [IN] condition for matching * - * * - * Return value: SUCCEED - matches, FAIL - otherwise * - * * - ******************************************************************************/ -static void check_internal_condition(const zbx_vector_db_event_t *esc_events, zbx_condition_t *condition) -{ - int ret; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - switch (condition->conditiontype) - { - case ZBX_CONDITION_TYPE_EVENT_TYPE: - ret = check_intern_event_type_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_HOST_GROUP: - ret = check_intern_host_group_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_HOST_TEMPLATE: - ret = check_intern_host_template_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_HOST: - ret = check_intern_host_condition(esc_events, condition); - break; - case ZBX_CONDITION_TYPE_EVENT_TAG: - check_condition_event_tag(esc_events, condition); - ret = SUCCEED; - break; - case ZBX_CONDITION_TYPE_EVENT_TAG_VALUE: - check_condition_event_tag_value(esc_events, condition); - ret = SUCCEED; - break; - default: - ret = FAIL; - zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->conditiontype, condition->conditionid); - } - - if (NOTSUPPORTED == ret) - { - zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", - (int)condition->op, condition->conditionid); - } - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); -} - -/****************************************************************************** - * * - * Purpose: check if multiple events matches single condition * - * * - * Parameters: esc_events - [IN] events to check * - * source - [IN] specific event source that need checking * - * condition - [IN/OUT] condition for matching, outputs * - * event ids that match condition * - * * - ******************************************************************************/ -static void check_events_condition(const zbx_vector_db_event_t *esc_events, int source, zbx_condition_t *condition) -{ - zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'" - " cond.value2:'%s'", __func__, condition->actionid, condition->conditionid, - condition->value, condition->value2); - - switch (source) - { - case EVENT_SOURCE_TRIGGERS: - check_trigger_condition(esc_events, condition); - break; - case EVENT_SOURCE_DISCOVERY: - check_discovery_condition(esc_events, condition); - break; - case EVENT_SOURCE_AUTOREGISTRATION: - check_autoregistration_condition(esc_events, condition); - break; - case EVENT_SOURCE_INTERNAL: - check_internal_condition(esc_events, condition); - break; - default: - zabbix_log(LOG_LEVEL_ERR, "unsupported event source [%d] for condition id [" ZBX_FS_UI64 "]", - source, condition->conditionid); - } - - zbx_vector_uint64_sort(&condition->eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); -} - -/****************************************************************************** - * * - * Purpose: check if event matches single condition * - * * - * Parameters: event - event to check * - * condition - condition for matching * - * * - * Return value: SUCCEED - matches, FAIL - otherwise * - * * - ******************************************************************************/ -int check_action_condition(zbx_db_event *event, zbx_condition_t *condition) -{ - int ret; - zbx_vector_db_event_t esc_events; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'" - " cond.value2:'%s'", __func__, condition->actionid, condition->conditionid, - ZBX_NULL2STR(condition->value), ZBX_NULL2STR(condition->value2)); - - zbx_vector_db_event_create(&esc_events); - - zbx_vector_db_event_append(&esc_events, event); - - check_events_condition(&esc_events, event->source, condition); - - ret = 0 != condition->eventids.values_num ? SUCCEED : FAIL; - - zbx_vector_db_event_destroy(&esc_events); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: check if action have to be processed for the event * - * (check all conditions of the action) * - * * - * Parameters: eventid - [IN] the id of event that will be checked * - * action - [IN] action for matching * - * * - * Return value: SUCCEED - matches, FAIL - otherwise * - * * - ******************************************************************************/ -static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t *action) -{ - zbx_condition_t *condition; - int condition_result, ret = SUCCEED, id_len, i; - unsigned char old_type = 0xff; - char *expression = NULL, tmp[ZBX_MAX_UINT64_LEN + 2], *ptr, error[256]; - double eval_result; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " eventsource:%d", __func__, - action->actionid, (int)action->eventsource); - - if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) - expression = zbx_strdup(expression, action->formula); - - for (i = 0; i < action->conditions.values_num; i++) - { - condition = (zbx_condition_t *)action->conditions.values[i]; - - if (ZBX_CONDITION_EVAL_TYPE_AND_OR == action->evaltype && - old_type == condition->conditiontype && SUCCEED == ret) - { - continue; /* short-circuit true OR condition block to the next AND condition */ - } - - condition_result = FAIL == zbx_vector_uint64_bsearch(&condition->eventids, eventid, - ZBX_DEFAULT_UINT64_COMPARE_FUNC) ? FAIL : SUCCEED; - - zabbix_log(LOG_LEVEL_DEBUG, " conditionid:" ZBX_FS_UI64 " conditiontype:%d cond.value:'%s' " - "cond.value2:'%s' result:%s", condition->conditionid, (int)condition->conditiontype, - condition->value, condition->value2, zbx_result_string(condition_result)); - - switch (action->evaltype) - { - case ZBX_CONDITION_EVAL_TYPE_AND_OR: - if (old_type == condition->conditiontype) /* assume conditions are sorted by type */ - { - if (SUCCEED == condition_result) - ret = SUCCEED; - } - else - { - if (FAIL == ret) - goto clean; - - ret = condition_result; - old_type = condition->conditiontype; - } - - break; - case ZBX_CONDITION_EVAL_TYPE_AND: - if (FAIL == condition_result) /* break if any AND condition is FALSE */ - { - ret = FAIL; - goto clean; - } - - break; - case ZBX_CONDITION_EVAL_TYPE_OR: - if (SUCCEED == condition_result) /* break if any OR condition is TRUE */ - { - ret = SUCCEED; - goto clean; - } - ret = FAIL; - - break; - case ZBX_CONDITION_EVAL_TYPE_EXPRESSION: - zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid); - id_len = strlen(tmp); - - for (ptr = expression; NULL != (ptr = strstr(ptr, tmp)); ptr += id_len) - { - *ptr = (SUCCEED == condition_result ? '1' : '0'); - memset(ptr + 1, ' ', id_len - 1); - } - - break; - default: - ret = FAIL; - goto clean; - } - } - - if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) - { - if (SUCCEED == zbx_evaluate(&eval_result, expression, error, sizeof(error), NULL)) - ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL); - - zbx_free(expression); - } -clean: - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: execute host, group, template operations linked to the action * - * * - * Parameters: action - action to execute operations for * - * * - * Comments: for message, command operations see * - * escalation_execute_operations(), * - * escalation_execute_recovery_operations(). * - * * - ******************************************************************************/ -static void execute_operations(const zbx_db_event *event, zbx_uint64_t actionid) -{ - zbx_db_result_t result; - zbx_db_row_t row; - zbx_uint64_t groupid, templateid, optagid; - zbx_vector_uint64_t lnk_templateids, del_templateids, new_groupids, del_groupids, new_optagids, - del_optagids; - int i; - zbx_config_t cfg; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __func__, actionid); - - zbx_vector_uint64_create(&lnk_templateids); - zbx_vector_uint64_create(&del_templateids); - zbx_vector_uint64_create(&new_groupids); - zbx_vector_uint64_create(&del_groupids); - zbx_vector_uint64_create(&new_optagids); - zbx_vector_uint64_create(&del_optagids); - - result = zbx_db_select( - "select o.operationtype,g.groupid,t.templateid,oi.inventory_mode,ot.optagid" - " from operations o" - " left join opgroup g on g.operationid=o.operationid" - " left join optemplate t on t.operationid=o.operationid" - " left join opinventory oi on oi.operationid=o.operationid" - " left join optag ot on ot.operationid=o.operationid" - " where o.actionid=" ZBX_FS_UI64 - " order by o.operationid", - actionid); - - zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_DISCOVERY_GROUPID | ZBX_CONFIG_FLAGS_DEFAULT_INVENTORY_MODE | - ZBX_CONFIG_FLAGS_AUDITLOG_ENABLED); - zbx_audit_init(cfg.auditlog_enabled); - - while (NULL != (row = zbx_db_fetch(result))) - { - int inventory_mode; - unsigned char operationtype; - - operationtype = (unsigned char)atoi(row[0]); - ZBX_DBROW2UINT64(groupid, row[1]); - ZBX_DBROW2UINT64(templateid, row[2]); - inventory_mode = (SUCCEED == zbx_db_is_null(row[3]) ? 0 : atoi(row[3])); - ZBX_DBROW2UINT64(optagid, row[4]); - - switch (operationtype) - { - case ZBX_OPERATION_TYPE_HOST_ADD: - op_host_add(event, &cfg); - break; - case ZBX_OPERATION_TYPE_HOST_REMOVE: - op_host_del(event); - break; - case ZBX_OPERATION_TYPE_HOST_ENABLE: - op_host_enable(event, &cfg); - break; - case ZBX_OPERATION_TYPE_HOST_DISABLE: - op_host_disable(event, &cfg); - break; - case ZBX_OPERATION_TYPE_GROUP_ADD: - if (0 != groupid) - zbx_vector_uint64_append(&new_groupids, groupid); - break; - case ZBX_OPERATION_TYPE_GROUP_REMOVE: - if (0 != groupid) - zbx_vector_uint64_append(&del_groupids, groupid); - break; - case ZBX_OPERATION_TYPE_TEMPLATE_ADD: - if (0 != templateid) - { - if (FAIL != (i = zbx_vector_uint64_search(&del_templateids, templateid, - ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - { - zbx_vector_uint64_remove(&del_templateids, i); - } - - zbx_vector_uint64_append(&lnk_templateids, templateid); - } - break; - case ZBX_OPERATION_TYPE_TEMPLATE_REMOVE: - if (0 != templateid) - { - if (FAIL != (i = zbx_vector_uint64_search(&lnk_templateids, templateid, - ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - { - zbx_vector_uint64_remove(&lnk_templateids, i); - } - - zbx_vector_uint64_append(&del_templateids, templateid); - } - break; - case ZBX_OPERATION_TYPE_HOST_INVENTORY: - op_host_inventory_mode(event, &cfg, inventory_mode); - break; - case ZBX_OPERATION_TYPE_HOST_TAGS_ADD: - if (0 != optagid) - zbx_vector_uint64_append(&new_optagids, optagid); - break; - case ZBX_OPERATION_TYPE_HOST_TAGS_REMOVE: - if (0 != optagid) - zbx_vector_uint64_append(&del_optagids, optagid); - break; - default: - ; - } - } - zbx_db_free_result(result); - - if (0 != del_templateids.values_num) - { - zbx_vector_uint64_sort(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - op_template_del(event, &del_templateids); - } - - if (0 != lnk_templateids.values_num) - { - zbx_vector_uint64_sort(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - op_template_add(event, &cfg, &lnk_templateids); - } - - if (0 != new_groupids.values_num) - { - zbx_vector_uint64_sort(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - op_groups_add(event, &cfg, &new_groupids); - } - - if (0 != del_groupids.values_num) - { - zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - op_groups_del(event, &del_groupids); - } - - if (0 != new_optagids.values_num || 0 != del_optagids.values_num) - op_add_del_tags(event, &cfg, &new_optagids, &del_optagids); - - zbx_vector_uint64_destroy(&del_groupids); - zbx_vector_uint64_destroy(&new_groupids); - zbx_vector_uint64_destroy(&del_templateids); - zbx_vector_uint64_destroy(&lnk_templateids); - zbx_vector_uint64_destroy(&new_optagids); - zbx_vector_uint64_destroy(&del_optagids); - - zbx_audit_flush(); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); -} - -/* data structures used to create new and recover existing escalations */ - -typedef struct -{ - zbx_uint64_t actionid; - const zbx_db_event *event; -} -zbx_escalation_new_t; - -/****************************************************************************** - * * - * Purpose: checks if the event is recovery event * - * * - * Parameters: event - [IN] the event to check * - * * - * Return value: SUCCEED - the event is recovery event * - * FAIL - otherwise * - * * - ******************************************************************************/ -static int is_recovery_event(const zbx_db_event *event) -{ - if (EVENT_SOURCE_TRIGGERS == event->source) - { - if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_VALUE_OK == event->value) - return SUCCEED; - } - else if (EVENT_SOURCE_INTERNAL == event->source) - { - switch (event->object) - { - case EVENT_OBJECT_TRIGGER: - if (TRIGGER_STATE_NORMAL == event->value) - return SUCCEED; - break; - case EVENT_OBJECT_ITEM: - if (ITEM_STATE_NORMAL == event->value) - return SUCCEED; - break; - case EVENT_OBJECT_LLDRULE: - if (ITEM_STATE_NORMAL == event->value) - return SUCCEED; - break; - } - } - - return FAIL; -} - -/****************************************************************************** - * * - * Purpose: to determine if event needs condition checks * - * * - * Parameters: event - [IN] event to validate * - * * - * Return value: SUCCEED - escalations possible for event * - * FAIL - escalations not possible for event * - * * - ******************************************************************************/ -static int is_escalation_event(const zbx_db_event *event) -{ - /* OK events can't start escalations - skip them */ - if (SUCCEED == is_recovery_event(event)) - return FAIL; - - if (0 != (event->flags & ZBX_FLAGS_DB_EVENT_NO_ACTION)) - return FAIL; - - if (0 == (event->flags & ZBX_FLAGS_DB_EVENT_CREATE)) - return FAIL; - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: compare to find equal conditions * - * * - * Parameters: d1 - [IN] condition structure to compare to d2 * - * d2 - [IN] condition structure to compare to d1 * - * * - * Return value: 0 - equal * - * not 0 - otherwise * - * * - ******************************************************************************/ -static int uniq_conditions_compare_func(const void *d1, const void *d2) -{ - const zbx_condition_t *condition1 = (const zbx_condition_t *)d1, *condition2 = (const zbx_condition_t *)d2; - int ret; - - ZBX_RETURN_IF_NOT_EQUAL(condition1->conditiontype, condition2->conditiontype); - ZBX_RETURN_IF_NOT_EQUAL(condition1->op, condition2->op); - - if (0 != (ret = strcmp(condition1->value, condition2->value))) - return ret; - - if (0 != (ret = strcmp(condition1->value2, condition2->value2))) - return ret; - - return 0; -} - -/****************************************************************************** - * * - * Purpose: generate hash based on condition values * - * * - * Parameters: data - [IN] condition structure * - * * - * Return value: hash is generated * - * * - ******************************************************************************/ -static zbx_hash_t uniq_conditions_hash_func(const void *data) -{ - const zbx_condition_t *condition = (const zbx_condition_t *)data; - zbx_hash_t hash; - - hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value, strlen(condition->value), ZBX_DEFAULT_HASH_SEED); - hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value2, strlen(condition->value2), hash); - hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->conditiontype, 1, hash); - hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->op, 1, hash); - - return hash; -} - -/****************************************************************************** - * * - * Purpose: add events that have escalation possible and skip others, also * - * adds according to source * - * * - * Parameters: events - [IN] events to apply actions for * - * events_num - [IN] number of events * - * esc_events - [OUT] events that need condition checks * - * * - ******************************************************************************/ -static void get_escalation_events(zbx_vector_db_event_t *events, zbx_vector_db_event_t *esc_events) -{ - for (int i = 0; i < events->values_num; i++) - { - zbx_db_event *event = events->values[i]; - - if (SUCCEED == is_escalation_event(event) && EVENT_SOURCE_COUNT > (size_t)event->source) - zbx_vector_db_event_append(&esc_events[event->source], event); - } -} - -/****************************************************************************** - * * - * Purpose: cleans condition data structure * - * * - * Parameters: condition - [IN] the condition data to free * - * * - ******************************************************************************/ -static void db_condition_clean(zbx_condition_t *condition) -{ - zbx_free(condition->value2); - zbx_free(condition->value); - zbx_vector_uint64_destroy(&condition->eventids); -} - -/****************************************************************************** - * * - * Purpose: cleans condition data structures from hashset * - * * - * Parameters: uniq_conditions - [IN] hashset with data structures to clean * - * * - ******************************************************************************/ -static void conditions_eval_clean(zbx_hashset_t *uniq_conditions) -{ - zbx_hashset_iter_t iter; - zbx_condition_t *condition; - - zbx_hashset_iter_reset(uniq_conditions, &iter); - - while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter))) - db_condition_clean(condition); -} - -/****************************************************************************** - * * - * Purpose: frees action evaluation data structure * - * * - * Parameters: action - [IN] the action evaluation to free * - * * - ******************************************************************************/ -static void zbx_action_eval_free(zbx_action_eval_t *action) -{ - zbx_free(action->formula); - - zbx_vector_ptr_destroy(&action->conditions); - - zbx_free(action); -} - -/****************************************************************************** - * * - * Purpose: make actions to point, to conditions from hashset, where all * - * conditions are unique, this ensures that we don't double check * - * same conditions. * - * * - * Parameters: actions - [IN/OUT] all conditions are added to hashset * - * then cleaned, actions will now * - * point to conditions from hashset. * - * for custom expression also * - * replaces formula * - * uniq_conditions - [OUT] unique conditions that actions * - * point to (several sources) * - * * - * Comments: The returned conditions must be freed with * - * conditions_eval_clean() function later. * - * * - ******************************************************************************/ -static void prepare_actions_conditions_eval(zbx_vector_ptr_t *actions, zbx_hashset_t *uniq_conditions) -{ - int i, j; - - for (i = 0; i < actions->values_num; i++) - { - zbx_action_eval_t *action = actions->values[i]; - - for (j = 0; j < action->conditions.values_num; j++) - { - zbx_condition_t *uniq_condition = NULL, *condition = action->conditions.values[j]; - - if (EVENT_SOURCE_COUNT <= action->eventsource) - { - db_condition_clean(condition); - } - else if (NULL == (uniq_condition = zbx_hashset_search(&uniq_conditions[action->eventsource], - condition))) - { - uniq_condition = zbx_hashset_insert(&uniq_conditions[action->eventsource], - condition, sizeof(zbx_condition_t)); - } - else - { - if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) - { - char search[ZBX_MAX_UINT64_LEN + 2]; - char replace[ZBX_MAX_UINT64_LEN + 2]; - char *old_formula; - - zbx_snprintf(search, sizeof(search), "{" ZBX_FS_UI64 "}", - condition->conditionid); - zbx_snprintf(replace, sizeof(replace), "{" ZBX_FS_UI64 "}", - uniq_condition->conditionid); - - old_formula = action->formula; - action->formula = zbx_string_replace(action->formula, search, replace); - zbx_free(old_formula); - } - - db_condition_clean(condition); - } - - zbx_free(action->conditions.values[j]); - action->conditions.values[j] = uniq_condition; - } - } -} - -/****************************************************************************** - * * - * Purpose: process all actions of each event in a list * - * * - * Parameters: events - [IN] events to apply actions for * - * closed_events - [IN] a vector of closed event data - * - * (PROBLEM eventid, OK eventid) pairs. * - * * - ******************************************************************************/ -void process_actions(zbx_vector_db_event_t *events, const zbx_vector_uint64_pair_t *closed_events) -{ - int i; - zbx_vector_ptr_t actions; - zbx_vector_ptr_t new_escalations; - zbx_vector_uint64_pair_t rec_escalations; - zbx_hashset_t uniq_conditions[EVENT_SOURCE_COUNT]; - zbx_vector_db_event_t esc_events[EVENT_SOURCE_COUNT]; - zbx_hashset_iter_t iter; - zbx_condition_t *condition; - zbx_dc_um_handle_t *um_handle; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() events_num:" ZBX_FS_SIZE_T, __func__, (zbx_fs_size_t)events->values_num); - - zbx_vector_ptr_create(&new_escalations); - zbx_vector_uint64_pair_create(&rec_escalations); - - for (i = 0; i < EVENT_SOURCE_COUNT; i++) - { - zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func); - zbx_vector_db_event_create(&esc_events[i]); - } - - zbx_vector_ptr_create(&actions); - zbx_dc_config_history_sync_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_NORMAL | ZBX_ACTION_OPCLASS_RECOVERY); - prepare_actions_conditions_eval(&actions, uniq_conditions); - get_escalation_events(events, esc_events); - - um_handle = zbx_dc_open_user_macros(); - - for (i = 0; i < EVENT_SOURCE_COUNT; i++) - { - if (0 == esc_events[i].values_num) - continue; - - zbx_vector_db_event_sort(&esc_events[i], compare_events); - - zbx_hashset_iter_reset(&uniq_conditions[i], &iter); - - while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter))) - check_events_condition(&esc_events[i], i, condition); - } - - zbx_dc_close_user_macros(um_handle); - - /* 1. All event sources: match PROBLEM events to action conditions, add them to 'new_escalations' list. */ - /* 2. EVENT_SOURCE_DISCOVERY, EVENT_SOURCE_AUTOREGISTRATION: execute operations (except command and message */ - /* operations) for events that match action conditions. */ - for (i = 0; i < events->values_num; i++) - { - int j; - const zbx_db_event *event; - - if (FAIL == is_escalation_event((event = events->values[i]))) - continue; - - for (j = 0; j < actions.values_num; j++) - { - zbx_action_eval_t *action = (zbx_action_eval_t *)actions.values[j]; - - if (action->eventsource != event->source) - continue; - - if (SUCCEED == check_action_conditions(event->eventid, action)) - { - zbx_escalation_new_t *new_escalation; - - /* command and message operations handled by escalators even for */ - /* EVENT_SOURCE_DISCOVERY and EVENT_SOURCE_AUTOREGISTRATION events */ - new_escalation = (zbx_escalation_new_t *)zbx_malloc(NULL, sizeof(zbx_escalation_new_t)); - new_escalation->actionid = action->actionid; - new_escalation->event = event; - zbx_vector_ptr_append(&new_escalations, new_escalation); - - if (EVENT_SOURCE_DISCOVERY == event->source || - EVENT_SOURCE_AUTOREGISTRATION == event->source) - { - execute_operations(event, action->actionid); - } - } - } - } - - for (i = 0; i < EVENT_SOURCE_COUNT; i++) - { - zbx_vector_db_event_destroy(&esc_events[i]); - conditions_eval_clean(&uniq_conditions[i]); - zbx_hashset_destroy(&uniq_conditions[i]); - } - - zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free); - zbx_vector_ptr_destroy(&actions); - - /* 3. Find recovered escalations and store escalationids in 'rec_escalation' by OK eventids. */ - if (0 != closed_events->values_num) - { - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - zbx_vector_uint64_t eventids; - zbx_db_row_t row; - zbx_db_result_t result; - int j, index; - - zbx_vector_uint64_create(&eventids); - - /* 3.1. Store PROBLEM eventids of recovered events in 'eventids'. */ - for (j = 0; j < closed_events->values_num; j++) - zbx_vector_uint64_append(&eventids, closed_events->values[j].first); - - /* 3.2. Select escalations that must be recovered. */ - zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, - "select eventid,escalationid" - " from escalations" - " where"); - - zbx_db_add_condition_alloc(&sql, &sql_alloc, &sql_offset, "eventid", eventids.values, eventids.values_num); - result = zbx_db_select("%s", sql); - - zbx_vector_uint64_pair_reserve(&rec_escalations, eventids.values_num); - - /* 3.3. Store the escalationids corresponding to the OK events in 'rec_escalations'. */ - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_pair_t pair; - - ZBX_STR2UINT64(pair.first, row[0]); - - if (FAIL == (index = zbx_vector_uint64_pair_bsearch(closed_events, pair, - ZBX_DEFAULT_UINT64_COMPARE_FUNC))) - { - THIS_SHOULD_NEVER_HAPPEN; - continue; - } - - pair.second = closed_events->values[index].second; - ZBX_DBROW2UINT64(pair.first, row[1]); - zbx_vector_uint64_pair_append(&rec_escalations, pair); - } - - zbx_db_free_result(result); - zbx_free(sql); - zbx_vector_uint64_destroy(&eventids); - } - - /* 4. Create new escalations in DB. */ - if (0 != new_escalations.values_num) - { - zbx_db_insert_t db_insert; - int j; - - zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid", - "itemid", "eventid", "r_eventid", "acknowledgeid", (char *)NULL); - - for (j = 0; j < new_escalations.values_num; j++) - { - zbx_uint64_t triggerid = 0, itemid = 0; - zbx_escalation_new_t *new_escalation; - - new_escalation = (zbx_escalation_new_t *)new_escalations.values[j]; - - switch (new_escalation->event->object) - { - case EVENT_OBJECT_TRIGGER: - triggerid = new_escalation->event->objectid; - break; - case EVENT_OBJECT_ITEM: - case EVENT_OBJECT_LLDRULE: - itemid = new_escalation->event->objectid; - break; - } - - zbx_db_insert_add_values(&db_insert, __UINT64_C(0), new_escalation->actionid, - (int)ESCALATION_STATUS_ACTIVE, triggerid, itemid, - new_escalation->event->eventid, __UINT64_C(0), __UINT64_C(0)); - - zbx_free(new_escalation); - } - - zbx_db_insert_autoincrement(&db_insert, "escalationid"); - zbx_db_insert_execute(&db_insert); - zbx_db_insert_clean(&db_insert); - } - - /* 5. Modify recovered escalations in DB. */ - if (0 != rec_escalations.values_num) - { - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - int j; - - zbx_vector_uint64_pair_sort(&rec_escalations, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - zbx_db_begin_multiple_update(&sql, &sql_alloc, &sql_offset); - - for (j = 0; j < rec_escalations.values_num; j++) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "update escalations set r_eventid=" ZBX_FS_UI64 ",nextcheck=0" - " where escalationid=" ZBX_FS_UI64 ";\n", - rec_escalations.values[j].second, rec_escalations.values[j].first); - - zbx_db_execute_overflowed_sql(&sql, &sql_alloc, &sql_offset); - } - - zbx_db_end_multiple_update(&sql, &sql_alloc, &sql_offset); - - if (16 < sql_offset) /* in ORACLE always present begin..end; */ - zbx_db_execute("%s", sql); - - zbx_free(sql); - } - - zbx_vector_uint64_pair_destroy(&rec_escalations); - zbx_vector_ptr_destroy(&new_escalations); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); -} - -/****************************************************************************** - * * - * Purpose: process actions for each acknowledgment in the array * - * * - * Parameters: event_ack - [IN] vector for eventid/ackid pairs * - * * - ******************************************************************************/ -int process_actions_by_acknowledgments(const zbx_vector_ptr_t *ack_tasks) -{ - zbx_vector_ptr_t actions; - zbx_hashset_t uniq_conditions[EVENT_SOURCE_COUNT]; - int processed_num = 0, knext = 0; - zbx_vector_uint64_t eventids; - zbx_ack_task_t *ack_task; - zbx_vector_ptr_t ack_escalations; - zbx_ack_escalation_t *ack_escalation; - zbx_vector_db_event_t esc_events[EVENT_SOURCE_COUNT]; - zbx_hashset_iter_t iter; - zbx_condition_t *condition; - zbx_dc_um_handle_t *um_handle; - zbx_vector_db_event_t events; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - zbx_vector_ptr_create(&ack_escalations); - - for (int i = 0; i < EVENT_SOURCE_COUNT; i++) - { - zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func); - zbx_vector_db_event_create(&esc_events[i]); - } - - zbx_vector_ptr_create(&actions); - zbx_dc_config_history_sync_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_ACKNOWLEDGE); - prepare_actions_conditions_eval(&actions, uniq_conditions); - - if (0 == actions.values_num) - goto out; - - zbx_vector_uint64_create(&eventids); - - for (int i = 0; i < ack_tasks->values_num; i++) - { - ack_task = (zbx_ack_task_t *)ack_tasks->values[i]; - zbx_vector_uint64_append(&eventids, ack_task->eventid); - } - - zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - zbx_vector_db_event_create(&events); - - zbx_db_get_events_by_eventids(&eventids, &events); - - for (int i = 0; i < events.values_num; i++) - { - zbx_db_event *event = events.values[i]; - - zbx_vector_db_event_append(&esc_events[event->source], event); - } - - um_handle = zbx_dc_open_user_macros(); - - for (int i = 0; i < EVENT_SOURCE_COUNT; i++) - { - if (0 == esc_events[i].values_num) - continue; - - zbx_vector_db_event_sort(&esc_events[i], compare_events); - - zbx_hashset_iter_reset(&uniq_conditions[i], &iter); - - while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter))) - check_events_condition(&esc_events[i], i, condition); - } - - zbx_dc_close_user_macros(um_handle); - - for (int i = 0; i < eventids.values_num; i++) - { - int kcurr = knext; - zbx_db_event *event = events.values[i]; - - while (knext < ack_tasks->values_num) - { - ack_task = (zbx_ack_task_t *)ack_tasks->values[knext]; - if (ack_task->eventid != event->eventid) - break; - knext++; - } - - if (0 == event->eventid || 0 == event->trigger.triggerid) - continue; - - for (int j = 0; j < actions.values_num; j++) - { - zbx_action_eval_t *action = (zbx_action_eval_t *)actions.values[j]; - - if (action->eventsource != event->source) - continue; - - if (SUCCEED != check_action_conditions(event->eventid, action)) - continue; - - for (int k = kcurr; k < knext; k++) - { - ack_task = (zbx_ack_task_t *)ack_tasks->values[k]; - - ack_escalation = (zbx_ack_escalation_t *)zbx_malloc(NULL, sizeof(zbx_ack_escalation_t)); - ack_escalation->taskid = ack_task->taskid; - ack_escalation->acknowledgeid = ack_task->acknowledgeid; - ack_escalation->actionid = action->actionid; - ack_escalation->eventid = event->eventid; - ack_escalation->triggerid = event->trigger.triggerid; - zbx_vector_ptr_append(&ack_escalations, ack_escalation); - } - } - } - - if (0 != ack_escalations.values_num) - { - zbx_db_insert_t db_insert; - - zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid", - "itemid", "eventid", "r_eventid", "acknowledgeid", (char *)NULL); - - zbx_vector_ptr_sort(&ack_escalations, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); - - for (int i = 0; i < ack_escalations.values_num; i++) - { - ack_escalation = (zbx_ack_escalation_t *)ack_escalations.values[i]; - - zbx_db_insert_add_values(&db_insert, __UINT64_C(0), ack_escalation->actionid, - (int)ESCALATION_STATUS_ACTIVE, ack_escalation->triggerid, __UINT64_C(0), - ack_escalation->eventid, __UINT64_C(0), ack_escalation->acknowledgeid); - } - - zbx_db_insert_autoincrement(&db_insert, "escalationid"); - zbx_db_insert_execute(&db_insert); - zbx_db_insert_clean(&db_insert); - - processed_num = ack_escalations.values_num; - } - - zbx_vector_db_event_clear_ext(&events, zbx_db_free_event); - zbx_vector_db_event_destroy(&events); - - zbx_vector_uint64_destroy(&eventids); -out: - for (int i = 0; i < EVENT_SOURCE_COUNT; i++) - { - zbx_vector_db_event_destroy(&esc_events[i]); - conditions_eval_clean(&uniq_conditions[i]); - zbx_hashset_destroy(&uniq_conditions[i]); - } - - zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free); - zbx_vector_ptr_destroy(&actions); - - zbx_vector_ptr_clear_ext(&ack_escalations, zbx_ptr_free); - zbx_vector_ptr_destroy(&ack_escalations); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s() processed_num:%d", __func__, processed_num); - - return processed_num; -} - -/****************************************************************************** - * * - * Purpose: reads actions from database * - * * - * Parameters: actionids - [IN] requested action ids * - * actions - [OUT] the array of actions * - * * - * Comments: use 'free_db_action' function to release allocated memory * - * * - ******************************************************************************/ -void get_db_actions_info(zbx_vector_uint64_t *actionids, zbx_vector_ptr_t *actions) -{ - zbx_db_result_t result; - zbx_db_row_t row; - char *filter = NULL; - size_t filter_alloc = 0, filter_offset = 0; - zbx_db_action *action; - - zbx_vector_uint64_sort(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - zbx_db_add_condition_alloc(&filter, &filter_alloc, &filter_offset, "actionid", actionids->values, - actionids->values_num); - - result = zbx_db_select("select actionid,name,status,eventsource,esc_period,pause_suppressed,notify_if_canceled," - "pause_symptoms" - " from actions" - " where%s order by actionid", filter); - - while (NULL != (row = zbx_db_fetch(result))) - { - char *tmp; - - action = (zbx_db_action *)zbx_malloc(NULL, sizeof(zbx_db_action)); - ZBX_STR2UINT64(action->actionid, row[0]); - ZBX_STR2UCHAR(action->status, row[2]); - ZBX_STR2UCHAR(action->eventsource, row[3]); - - tmp = zbx_strdup(NULL, row[4]); - zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &tmp, ZBX_MACRO_TYPE_COMMON, NULL, 0); - if (SUCCEED != zbx_is_time_suffix(tmp, &action->esc_period, ZBX_LENGTH_UNLIMITED)) - { - zabbix_log(LOG_LEVEL_WARNING, "Invalid default operation step duration \"%s\" for action" - " \"%s\", using default value of 1 hour", tmp, row[1]); - action->esc_period = SEC_PER_HOUR; - } - zbx_free(tmp); - - ZBX_STR2UCHAR(action->pause_suppressed, row[5]); - ZBX_STR2UCHAR(action->notify_if_canceled, row[6]); - ZBX_STR2UCHAR(action->pause_symptoms, row[7]); - action->name = zbx_strdup(NULL, row[1]); - action->recovery = ZBX_ACTION_RECOVERY_NONE; - - zbx_vector_ptr_append(actions, action); - } - zbx_db_free_result(result); - - result = zbx_db_select("select actionid from operations where recovery=%d and%s", - ZBX_OPERATION_MODE_RECOVERY, filter); - - while (NULL != (row = zbx_db_fetch(result))) - { - zbx_uint64_t actionid; - int index; - - ZBX_STR2UINT64(actionid, row[0]); - if (FAIL != (index = zbx_vector_ptr_bsearch(actions, &actionid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) - { - action = (zbx_db_action *)actions->values[index]; - action->recovery = ZBX_ACTION_RECOVERY_OPERATIONS; - } - } - zbx_db_free_result(result); - - zbx_free(filter); -} - -void free_db_action(zbx_db_action *action) -{ - zbx_free(action->name); - zbx_free(action); -}