diff options
author | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2021-08-24 11:29:37 +0300 |
---|---|---|
committer | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2021-08-24 11:29:37 +0300 |
commit | 69877db8798e7fd85ffe91c459f7b37cb20cf39f (patch) | |
tree | b9689610440266b0794573540e9abfe52d6a7f5c | |
parent | e08c614a500dccc2d0c1b946680c2bf001952dd9 (diff) |
....I...S. [ZBXNEXT-6787] reworked logics, refactored
-rw-r--r-- | include/service_protocol.h | 3 | ||||
-rw-r--r-- | src/libs/zbxservice/service_protocol.c | 56 | ||||
-rw-r--r-- | src/zabbix_server/escalator/escalator.c | 442 | ||||
-rw-r--r-- | src/zabbix_server/service/service_manager.c | 23 |
4 files changed, 323 insertions, 201 deletions
diff --git a/include/service_protocol.h b/include/service_protocol.h index 97520a8608e..41f2a89a94e 100644 --- a/include/service_protocol.h +++ b/include/service_protocol.h @@ -45,5 +45,8 @@ void zbx_service_serialize_parent_service(unsigned char **data, size_t *data_all zbx_uint64_t serviceid, zbx_vector_tags_t *tags); void zbx_service_deserialize_parent_services(const unsigned char *data, zbx_uint32_t size, zbx_vector_ptr_t *parent_services); +void zbx_service_serialize_parentids(unsigned char **data, zbx_uint32_t *data_alloc, zbx_uint32_t *data_offset, + const zbx_vector_uint64_t *ids); +void zbx_service_deserialize_parentids(const unsigned char *data, zbx_uint32_t size, zbx_vector_uint64_t *ids); #endif diff --git a/src/libs/zbxservice/service_protocol.c b/src/libs/zbxservice/service_protocol.c index 214001aaec0..b7025d2d3d4 100644 --- a/src/libs/zbxservice/service_protocol.c +++ b/src/libs/zbxservice/service_protocol.c @@ -311,3 +311,59 @@ void zbx_service_deserialize_rootcause(const unsigned char *data, zbx_uint32_t s } } } + +void zbx_service_serialize_parentids(unsigned char **data, zbx_uint32_t *data_alloc, zbx_uint32_t *data_offset, + const zbx_vector_uint64_t *ids) +{ + zbx_uint32_t data_len = 0; + int i; + unsigned char *ptr; + + zbx_serialize_prepare_value(data_len, ids->values_num); + + for (i = 0; i < ids->values_num; i++) + zbx_serialize_prepare_value(data_len, ids->values[i]); + + if (NULL != *data) + { + while (data_len > *data_alloc - *data_offset) + { + *data_alloc *= 2; + *data = (unsigned char *)zbx_realloc(*data, *data_alloc); + } + } + else + *data = (unsigned char *)zbx_malloc(NULL, (*data_alloc = MAX(1024, data_len))); + + ptr = *data + *data_offset; + *data_offset += data_len; + + ptr += zbx_serialize_value(ptr, ids->values_num); + + for (i = 0; i < ids->values_num; i++) + ptr += zbx_serialize_value(ptr, ids->values[i]); +} + +void zbx_service_deserialize_parentids(const unsigned char *data, zbx_uint32_t size, zbx_vector_uint64_t *ids) +{ + const unsigned char *end = data + size; + + while (data < end) + { + int values_num, i; + + data += zbx_deserialize_value(data, &values_num); + + if (0 == values_num) + continue; + + for (i = 0; i < values_num; i++) + { + zbx_uint64_t id; + + data += zbx_deserialize_value(data, &id); + + zbx_vector_uint64_append(ids, id); + } + } +}
\ No newline at end of file diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c index 35ee5857d3a..5017e4791e1 100644 --- a/src/zabbix_server/escalator/escalator.c +++ b/src/zabbix_server/escalator/escalator.c @@ -86,30 +86,23 @@ zbx_tag_filter_t; typedef struct { - char *read_tag; - char *read_value; - char *write_tag; - char *write_value; -} -zbx_service_tag_rule_t; + /* the role identifier */ + zbx_uint64_t roleid; -typedef struct -{ - zbx_uint64_t roleid; - char *name; - int type; - zbx_uint64_t value_serviceid; - char *value_str; - zbx_uint64_t value_int; + /* 0 if services.read is set to 0 and services.write is either 0 or absent. 1 otherwise. */ + unsigned char default_read; + + /* the service identifiers listed by services.read.id.* and services.write.id.* */ + zbx_vector_uint64_t serviceids; + + /* the service.read.tag.* and service.write.tag.* rules */ + zbx_vector_tags_t tags; } -zbx_service_role_rule_t; +zbx_service_role_t; ZBX_VECTOR_DECL(service_alarm, zbx_service_alarm_t) ZBX_VECTOR_IMPL(service_alarm, zbx_service_alarm_t) -ZBX_PTR_VECTOR_DECL(service_role_rule, zbx_service_role_rule_t*) -ZBX_PTR_VECTOR_IMPL(service_role_rule, zbx_service_role_rule_t*) - typedef enum { ZBX_VC_UPDATE_STATS, @@ -402,156 +395,214 @@ out: return perm; } -static int get_service_global_rights_enabled(zbx_uint64_t roleid, zbx_vector_service_role_rule_t *rolerules) +static int check_parent_service_intersection(zbx_vector_uint64_t *parent_ids, zbx_vector_uint64_t *role_ids) { int i; - for (i = 0; i < rolerules->values_num; i++) + for (i = 0; i < parent_ids->values_num; i++) { - zbx_service_role_rule_t *rule; - - rule = rolerules->values[i]; - - if (ZBX_ROLE_RULE_TYPE_INT == rule->type && roleid == rule->roleid) - { - if (0 == strcmp(rule->name, "services.read") && 1 == rule->value_int) - return SUCCEED; - } + if (SUCCEED == zbx_vector_uint64_bsearch(role_ids, parent_ids->values[i], ZBX_DEFAULT_UINT64_COMPARE_FUNC)) + return PERM_READ; } - return FAIL; + return PERM_DENY; } -static void check_cached_rule_serviceids(zbx_uint64_t roleid, zbx_uint64_t serviceid, - zbx_vector_service_role_rule_t *rolerules, int *perm) +static int check_db_parent_rule_tag_match(zbx_vector_uint64_t *parent_ids, + zbx_vector_tags_t *tags) { - int i; + DB_RESULT result; + DB_ROW row; + char *sql = NULL, *read_tag = NULL, *read_value = NULL, *write_tag = NULL, *write_value = NULL; + int i, perm = PERM_DENY; + size_t sql_alloc = 0, sql_offset = 0; - for (i = 0; i < rolerules->values_num; i++) - { - zbx_service_role_rule_t *rule; + if (0 == parent_ids->values_num || 0 == tags->values_num) + return PERM_DENY; + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select null from service_tag where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "serviceid", parent_ids->values, + parent_ids->values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and ("); - rule = rolerules->values[i]; + for (i = 0; i < tags->values_num; i++) + { + zbx_tag_t *tag = tags->values[i]; - if (ZBX_ROLE_RULE_TYPE_SERVICEID != rule->type) - continue; + if (NULL == tag->value) + { + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "(tag='%s')", tag->tag); + } + else + { + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "(tag='%s' and value='%s')", tag->tag, + tag->value); + } - if (roleid == rule->roleid && serviceid == rule->value_serviceid) + if (i + 1 < tags->values_num) { - if (0 == strncmp("services.read.", rule->name, ZBX_CONST_STRLEN("services.read."))) - *perm |= PERM_READ; - else if (0 == strncmp("services.write.", rule->name, ZBX_CONST_STRLEN("services.write."))) - *perm |= PERM_READ_WRITE; + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " or"); } } -} -static void check_service_tags_rule_match(zbx_uint64_t roleid, int *perm, const zbx_vector_ptr_t *service_tags, - zbx_vector_service_role_rule_t *rolerules, zbx_service_tag_rule_t *tag_rules) -{ - int i; + result = DBselect("%s) limit 1", sql); - for (i = 0; i < rolerules->values_num; i++) + if (NULL != (row = DBfetch(result))) { - zbx_service_role_rule_t *rule; + perm = PERM_READ; + } - rule = rolerules->values[i]; + DBfree_result(result); + zbx_free(sql); - if (ZBX_ROLE_RULE_TYPE_STR != rule->type || rule->roleid != roleid) - continue; + return perm; +} - if (0 == strcmp(rule->name, "services.read.tag.name")) - tag_rules->read_tag = rule->value_str; - else if (0 == strcmp(rule->name, "services.read.tag.value")) - tag_rules->read_value = rule->value_str; - else if (0 == strcmp(rule->name, "services.write.tag.name")) - tag_rules->write_tag = rule->value_str; - else if (0 == strcmp(rule->name, "services.write.tag.value")) - tag_rules->write_value = rule->value_str; - } +static int check_service_tags_rule_match(const zbx_vector_ptr_t *service_tags, const zbx_vector_tags_t *role_tags) +{ + int i, perm = PERM_DENY; + char *read_tag = NULL, *read_value = NULL, *write_tag = NULL, *write_value = NULL; - for (i = 0; i < service_tags->values_num; i++) + for (i = 0; i < role_tags->values_num; i++) { - zbx_tag_t *tag; - - tag = (zbx_tag_t*)service_tags->values[i]; + zbx_tag_t *role_tag = role_tags->values[i]; - if (NULL != tag_rules->read_tag) + if (0 == strncmp(role_tag->tag, "services.read.tag.name", ZBX_CONST_STRLEN("services.read.tag.name"))) { - if (0 == strcmp(tag_rules->read_tag, tag->tag)) - { - if (NULL == tag_rules->read_value || 0 == strcmp(tag_rules->read_value, tag->value)) - *perm |= PERM_READ; - } + read_tag = role_tag->value; } - - if (NULL != tag_rules->write_tag) + else if (0 == strncmp(role_tag->tag, "services.read.tag.value", + ZBX_CONST_STRLEN("services.read.tag.value"))) { - if (0 == strcmp(tag_rules->write_tag, tag->tag)) - { - if (NULL == tag_rules->write_value || 0 == strcmp(tag_rules->write_value, tag->value)) - { - *perm |= PERM_READ_WRITE; - } - } + read_value = role_tag->value; + } + else if (0 == strncmp(role_tag->tag, "services.write.tag.name", + ZBX_CONST_STRLEN("services.write.tag.name"))) + { + write_tag = role_tag->value; + } + else if (0 == strncmp(role_tag->tag, "services.write.tag.value", + ZBX_CONST_STRLEN("services.write.tag.value"))) + { + write_value = role_tag->value; } } -} -static void check_parent_service_intersection(zbx_vector_uint64_t *parent_ids, zbx_uint64_t roleid, - zbx_vector_service_role_rule_t *rolerules, int *perm) -{ - int i; + if (NULL == read_tag) + return perm; - for (i = 0; i < parent_ids->values_num; i++) + for (i = 0; i < service_tags->values_num; i++) { - zbx_uint64_t parent_id; + zbx_tag_t *tag = (zbx_tag_t*)service_tags->values[i]; - parent_id = parent_ids->values[i]; - check_cached_rule_serviceids(roleid, parent_id, rolerules, perm); + if (0 == strcmp(read_tag, tag->tag)) + { + if (NULL == read_value || 0 == strcmp(read_value, tag->value)) + perm |= PERM_READ; + } + else if (NULL != write_tag && 0 == strcmp(write_tag, tag->tag)) + { + if (NULL == write_value || 0 == strcmp(write_value, tag->value)) + perm |= PERM_READ_WRITE; + } } + + return perm; } -static void check_db_parent_rule_tag_match(zbx_vector_uint64_t *parent_ids, - zbx_service_tag_rule_t *tag_rules, int *perm) +static int zbx_db_cache_service_role(zbx_service_role_t *role) { DB_RESULT result; DB_ROW row; - char *serviceid_sql = NULL, *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0, serviceid_sql_alloc = 0, serviceid_sql_offset = 0; + unsigned char services_read = 1, services_write = -1; + int ret = FAIL; - if (0 == parent_ids->values_num || NULL == tag_rules->read_tag && NULL == tag_rules->write_tag) - return; + result = DBselect("select name,roleid,value_int,value_str,value_serviceid,type from role_rule where roleid=" + ZBX_FS_UI64 " order by name", role->roleid); - DBadd_condition_alloc(&serviceid_sql, &serviceid_sql_alloc, &serviceid_sql_offset, "serviceid", parent_ids->values, - parent_ids->values_num); + while (NULL != (row = DBfetch(result))) + { + zbx_uint64_t type; + char *name = row[0]; - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select null from service_tag where%s and (", serviceid_sql); + ZBX_STR2UINT64(type, row[5]); - if (NULL != tag_rules->read_tag) - { - if (NULL != tag_rules->read_value) - zbx_strdcatf(sql, "(tag='%s' and value='%s') ", tag_rules->read_tag, tag_rules->read_value); - else - zbx_strdcatf(sql, "tag='%s' ", tag_rules->read_tag); - } + ret = SUCCEED; - if (NULL != tag_rules->write_tag) - { - if (NULL != tag_rules->write_value) - zbx_strdcatf(sql, "or (tag='%s' and value='%s') ", tag_rules->write_tag, tag_rules->write_value); - else - zbx_strdcatf(sql, "or tag='%s' ", tag_rules->write_tag); + if (ZBX_ROLE_RULE_TYPE_INT == type) /* services.read or services.write */ + { + char *value_int = row[2]; + + if (0 == strcmp("services.read", name)) + ZBX_STR2UCHAR(services_read, value_int); + else if (0 == strcmp("services.write", name)) + ZBX_STR2UCHAR(services_write, value_int); + } + else if (ZBX_ROLE_RULE_TYPE_STR == type) /* services.read.tag.* / services.write.tag.* */ + { + char *value_str = row[3]; + zbx_tag_t *tag; + size_t name_len; + + if (NULL == row[3]) + continue; + + name_len = strlen(name); + + if (name_len < ZBX_CONST_STRLEN("tag.value")) + continue; + + if (0 == strcmp("tag.name", name + name_len - ZBX_CONST_STRLEN("tag.name"))) + { + tag = (zbx_tag_t*)zbx_malloc(NULL, sizeof(zbx_tag_t)); + tag->tag = zbx_strdup(NULL, value_str); + tag->value = NULL; + zbx_vector_tags_append(&role->tags, tag); + } + else if (0 == strcmp("tag.value", name + name_len - ZBX_CONST_STRLEN("tag.value"))) + { + if (role->tags.values_num == 0) + continue; + + tag = role->tags.values[role->tags.values_num - 1]; + tag->value = zbx_strdup(NULL, value_str); + } + + } + else if (ZBX_ROLE_RULE_TYPE_SERVICEID == type) /* services.read.id.<idx> / services.write.id.<idx>*/ + { + char *value_serviceid = row[4]; + zbx_uint64_t serviceid; + + if (NULL == value_serviceid) + continue; + + if (0 != strncmp(name, "services.read.id", ZBX_CONST_STRLEN("service.read.id")) && + 0 != strncmp(name, "services.write.id", ZBX_CONST_STRLEN("service.write.id"))) + { + continue; + } + + ZBX_STR2UINT64(serviceid, value_serviceid); + + zbx_vector_uint64_append(&role->serviceids, serviceid); + } } - result = DBselect("%s) limit 1", sql); + if (0 == services_read && services_write < 1) + role->default_read = 0; + else + role->default_read = 1; - if (NULL != (row = DBfetch(result))) + if (role->serviceids.values_num > 0) { - *perm |= PERM_READ; + zbx_vector_uint64_sort(&role->serviceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_uniq(&role->serviceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); } DBfree_result(result); + + return ret; } /****************************************************************************** @@ -565,7 +616,7 @@ static void check_db_parent_rule_tag_match(zbx_vector_uint64_t *parent_ids, * * ******************************************************************************/ static int get_service_permission(zbx_uint64_t userid, char **user_timezone, const DB_SERVICE *service, - zbx_vector_service_role_rule_t *rolerules) + zbx_hashset_t *roles) { int perm = PERM_DENY; unsigned char *data = NULL; @@ -573,23 +624,45 @@ static int get_service_permission(zbx_uint64_t userid, char **user_timezone, con zbx_user_t user = {.userid = userid}; zbx_ipc_message_t response; zbx_vector_uint64_t parent_ids; - zbx_service_tag_rule_t tag_rules = { 0 }; + zbx_service_role_t role_local, *role; user.type = get_user_info(userid, &user.roleid, user_timezone); + role_local.roleid = user.roleid; + + if (NULL == (role = zbx_hashset_search(roles, &role_local))) + { + zbx_vector_uint64_create(&role_local.serviceids); + zbx_vector_tags_create(&role_local.tags); + zbx_db_cache_service_role(&role_local); + zbx_hashset_insert(roles, &role, sizeof(zbx_service_role_t)); + role = &role_local; + } + // check if global read rights are not disabled (services.read:0). In this case individual role rules can be skipped. - if (SUCCEED == get_service_global_rights_enabled(user.roleid, rolerules)) - return perm; + if (1 == role->default_read) + return PERM_READ; // read read/write rule rights - check_cached_rule_serviceids(user.roleid, service->serviceid, rolerules, &perm); - if (perm > PERM_DENY) - return perm; + if (SUCCEED == zbx_vector_uint64_bsearch(&role->serviceids, service->serviceid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)) + return PERM_READ; // check if service tags does not match tag rules - check_service_tags_rule_match(user.roleid, &perm, &service->service_tags, rolerules, &tag_rules); - if (perm > PERM_DENY) + if (PERM_DENY < (perm = check_service_tags_rule_match(&service->service_tags, &role->tags))) + { + zabbix_log(3, "check 3 - ok"); return perm; + } + else + { + zabbix_log(3, "check 3 - fail"); + } + + zabbix_log(3, "tag count = %lu", role->tags.values_num); + for (int u = 0; u < role->tags.values_num; u++) + { + zabbix_log(3, "tag '%s' -> '%s'", role->tags.values[u]->tag, role->tags.values[u]->value); + } // get service parent ids from service manager zbx_service_serialize_id(&data, &data_alloc, &data_offset, service->serviceid); @@ -600,15 +673,17 @@ static int get_service_permission(zbx_uint64_t userid, char **user_timezone, con zbx_ipc_message_init(&response); zbx_service_send(ZBX_IPC_SERVICE_SERVICE_PARENT_LIST, data, data_offset, &response); zbx_vector_uint64_create(&parent_ids); - zbx_service_deserialize_ids(response.data, response.size, &parent_ids); + zbx_service_deserialize_parentids(response.data, response.size, &parent_ids); zbx_ipc_message_clean(&response); // check if the returned vector doesn't intersect rule serviceids vector - check_parent_service_intersection(&parent_ids, user.roleid, rolerules, &perm); - if (perm > PERM_DENY) + if (PERM_DENY < (perm = check_parent_service_intersection(&parent_ids, &role->serviceids))) + return perm; + + + if (PERM_DENY < (perm = check_db_parent_rule_tag_match(&parent_ids, &role->tags))) return perm; - check_db_parent_rule_tag_match(&parent_ids, &tag_rules, &perm); out: zbx_vector_uint64_destroy(&parent_ids); zbx_free(data); @@ -790,7 +865,7 @@ out: static void add_object_msg(zbx_uint64_t actionid, zbx_uint64_t operationid, ZBX_USER_MSG **user_msg, const DB_EVENT *event, const DB_EVENT *r_event, const DB_ACKNOWLEDGE *ack, const zbx_service_alarm_t *service_alarm, const DB_SERVICE *service, int macro_type, - unsigned char evt_src, unsigned char op_mode, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) + unsigned char evt_src, unsigned char op_mode, const char *default_timezone, zbx_hashset_t *roles) { DB_RESULT result; DB_ROW row; @@ -834,7 +909,7 @@ static void add_object_msg(zbx_uint64_t actionid, zbx_uint64_t operationid, ZBX_ goto clean; break; case EVENT_OBJECT_SERVICE: - if (PERM_READ > get_service_permission(userid, &user_timezone, service, rolerules)) + if (PERM_READ > get_service_permission(userid, &user_timezone, service, roles)) goto clean; break; default: @@ -873,7 +948,7 @@ static void add_sentusers_msg(ZBX_USER_MSG **user_msg, zbx_uint64_t actionid, zb const DB_EVENT *event, const DB_EVENT *r_event, const DB_ACKNOWLEDGE *ack, const zbx_service_alarm_t *service_alarm, const DB_SERVICE *service, unsigned char evt_src, unsigned char op_mode, - const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) + const char *default_timezone, zbx_hashset_t *roles) { char *sql = NULL; DB_RESULT result; @@ -936,7 +1011,7 @@ static void add_sentusers_msg(ZBX_USER_MSG **user_msg, zbx_uint64_t actionid, zb goto clean; break; case EVENT_OBJECT_SERVICE: - if (PERM_READ > get_service_permission(userid, &user_timezone, service, rolerules)) + if (PERM_READ > get_service_permission(userid, &user_timezone, service, roles)) goto clean; break; default: @@ -972,7 +1047,7 @@ clean: * * ******************************************************************************/ static void add_sentusers_msg_esc_cancel(ZBX_USER_MSG **user_msg, zbx_uint64_t actionid, const DB_EVENT *event, - const char *error, const char *default_timezone, const DB_SERVICE *service, zbx_vector_service_role_rule_t *rolerules) + const char *error, const char *default_timezone, const DB_SERVICE *service, zbx_hashset_t *roles) { char *message_dyn, *sql = NULL; DB_RESULT result; @@ -1027,7 +1102,7 @@ static void add_sentusers_msg_esc_cancel(ZBX_USER_MSG **user_msg, zbx_uint64_t a goto clean; break; case EVENT_OBJECT_SERVICE: - if (PERM_READ > get_service_permission(userid, &user_timezone, service, rolerules)) + if (PERM_READ > get_service_permission(userid, &user_timezone, service, roles)) goto clean; break; default: @@ -1836,7 +1911,7 @@ succeed: } static void escalation_execute_operations(DB_ESCALATION *escalation, const DB_EVENT *event, const DB_ACTION *action, - const DB_SERVICE *service, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) + const DB_SERVICE *service, const char *default_timezone, zbx_hashset_t *roles) { DB_RESULT result; DB_ROW row; @@ -1895,7 +1970,7 @@ static void escalation_execute_operations(DB_ESCALATION *escalation, const DB_EV case OPERATION_TYPE_MESSAGE: add_object_msg(action->actionid, operationid, &user_msg, event, NULL, NULL, NULL, service, MACRO_TYPE_MESSAGE_NORMAL, action->eventsource, - ZBX_OPERATION_MODE_NORMAL, default_timezone, rolerules); + ZBX_OPERATION_MODE_NORMAL, default_timezone, roles); break; case OPERATION_TYPE_COMMAND: execute_commands(event, NULL, NULL, NULL, service, action->actionid, operationid, @@ -1964,7 +2039,7 @@ static void escalation_execute_operations(DB_ESCALATION *escalation, const DB_EV ******************************************************************************/ static void escalation_execute_recovery_operations(const DB_EVENT *event, const DB_EVENT *r_event, const DB_ACTION *action, const DB_SERVICE *service, const char *default_timezone, - zbx_vector_service_role_rule_t *rolerules) + zbx_hashset_t *roles) { DB_RESULT result; DB_ROW row; @@ -1994,12 +2069,12 @@ static void escalation_execute_recovery_operations(const DB_EVENT *event, const case OPERATION_TYPE_MESSAGE: add_object_msg(action->actionid, operationid, &user_msg, event, r_event, NULL, NULL, service, MACRO_TYPE_MESSAGE_RECOVERY, action->eventsource, - ZBX_OPERATION_MODE_RECOVERY, default_timezone, rolerules); + ZBX_OPERATION_MODE_RECOVERY, default_timezone, roles); break; case OPERATION_TYPE_RECOVERY_MESSAGE: add_sentusers_msg(&user_msg, action->actionid, operationid, event, r_event, NULL, NULL, service, action->eventsource, ZBX_OPERATION_MODE_RECOVERY, - default_timezone, rolerules); + default_timezone, roles); break; case OPERATION_TYPE_COMMAND: execute_commands(event, r_event, NULL, NULL, service, action->actionid, operationid, 1, @@ -2031,7 +2106,7 @@ static void escalation_execute_recovery_operations(const DB_EVENT *event, const ******************************************************************************/ static void escalation_execute_update_operations(const DB_EVENT *event, const DB_EVENT *r_event, const DB_ACTION *action, const DB_ACKNOWLEDGE *ack, const zbx_service_alarm_t *service_alarm, - const DB_SERVICE *service, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) + const DB_SERVICE *service, const char *default_timezone, zbx_hashset_t *roles) { DB_RESULT result; DB_ROW row; @@ -2061,12 +2136,12 @@ static void escalation_execute_update_operations(const DB_EVENT *event, const DB case OPERATION_TYPE_MESSAGE: add_object_msg(action->actionid, operationid, &user_msg, event, r_event, ack, service_alarm, service, MACRO_TYPE_MESSAGE_UPDATE, action->eventsource, - ZBX_OPERATION_MODE_UPDATE, default_timezone, rolerules); + ZBX_OPERATION_MODE_UPDATE, default_timezone, roles); break; case OPERATION_TYPE_UPDATE_MESSAGE: add_sentusers_msg(&user_msg, action->actionid, operationid, event, r_event, ack, service_alarm, service, action->eventsource, ZBX_OPERATION_MODE_UPDATE, - default_timezone, rolerules); + default_timezone, roles); if (NULL != ack) { add_sentusers_ack_msg(&user_msg, action->actionid, operationid, event, r_event, @@ -2402,7 +2477,7 @@ static void escalation_log_cancel_warning(const DB_ESCALATION *escalation, const * * ******************************************************************************/ static void escalation_cancel(DB_ESCALATION *escalation, const DB_ACTION *action, const DB_EVENT *event, - const char *error, const char *default_timezone, const DB_SERVICE *service, zbx_vector_service_role_rule_t *rolerules) + const char *error, const char *default_timezone, const DB_SERVICE *service, zbx_hashset_t *roles) { ZBX_USER_MSG *user_msg = NULL; @@ -2413,7 +2488,7 @@ static void escalation_cancel(DB_ESCALATION *escalation, const DB_ACTION *action if (NULL != action && NULL != event && 0 != event->trigger.triggerid && 0 != escalation->esc_step) { add_sentusers_msg_esc_cancel(&user_msg, action->actionid, event, ZBX_NULL2EMPTY_STR(error), - default_timezone, service, rolerules); + default_timezone, service, roles); flush_user_msg(&user_msg, escalation->esc_step, event, NULL, action->actionid, NULL, NULL, NULL); } @@ -2435,12 +2510,12 @@ static void escalation_cancel(DB_ESCALATION *escalation, const DB_ACTION *action * * ******************************************************************************/ static void escalation_execute(DB_ESCALATION *escalation, const DB_ACTION *action, const DB_EVENT *event, - const DB_SERVICE *service, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) + const DB_SERVICE *service, const char *default_timezone, zbx_hashset_t *roles) { zabbix_log(LOG_LEVEL_DEBUG, "In %s() escalationid:" ZBX_FS_UI64 " status:%s", __func__, escalation->escalationid, zbx_escalation_status_string(escalation->status)); - escalation_execute_operations(escalation, event, action, service, default_timezone, rolerules); + escalation_execute_operations(escalation, event, action, service, default_timezone, roles); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } @@ -2459,12 +2534,12 @@ static void escalation_execute(DB_ESCALATION *escalation, const DB_ACTION *actio ******************************************************************************/ static void escalation_recover(DB_ESCALATION *escalation, const DB_ACTION *action, const DB_EVENT *event, const DB_EVENT *r_event, const DB_SERVICE *service, const char *default_timezone, - zbx_vector_service_role_rule_t *rolerules) + zbx_hashset_t *roles) { zabbix_log(LOG_LEVEL_DEBUG, "In %s() escalationid:" ZBX_FS_UI64 " status:%s", __func__, escalation->escalationid, zbx_escalation_status_string(escalation->status)); - escalation_execute_recovery_operations(event, r_event, action, service, default_timezone, rolerules); + escalation_execute_recovery_operations(event, r_event, action, service, default_timezone, roles); escalation->status = ESCALATION_STATUS_COMPLETED; @@ -2484,7 +2559,7 @@ static void escalation_recover(DB_ESCALATION *escalation, const DB_ACTION *actio * * ******************************************************************************/ static void escalation_acknowledge(DB_ESCALATION *escalation, const DB_ACTION *action, const DB_EVENT *event, - const DB_EVENT *r_event, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) + const DB_EVENT *r_event, const char *default_timezone, zbx_hashset_t *roles) { DB_ROW row; DB_RESULT result; @@ -2510,7 +2585,7 @@ static void escalation_acknowledge(DB_ESCALATION *escalation, const DB_ACTION *a ack.old_severity = atoi(row[4]); ack.new_severity = atoi(row[5]); - escalation_execute_update_operations(event, r_event, action, &ack, NULL, NULL, default_timezone, rolerules); + escalation_execute_update_operations(event, r_event, action, &ack, NULL, NULL, default_timezone, roles); } DBfree_result(result); @@ -2536,13 +2611,13 @@ static void escalation_acknowledge(DB_ESCALATION *escalation, const DB_ACTION *a ******************************************************************************/ static void escalation_update(DB_ESCALATION *escalation, const DB_ACTION *action, const DB_EVENT *event, const zbx_service_alarm_t *service_alarm, const DB_SERVICE *service, - const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) + const char *default_timezone, zbx_hashset_t *roles) { zabbix_log(LOG_LEVEL_DEBUG, "In %s() escalationid:" ZBX_FS_UI64 " servicealarmid:" ZBX_FS_UI64 " status:%s", __func__, escalation->escalationid, escalation->servicealarmid, zbx_escalation_status_string(escalation->status)); - escalation_execute_update_operations(event, NULL, action, NULL, service_alarm, service, default_timezone, rolerules); + escalation_execute_update_operations(event, NULL, action, NULL, service_alarm, service, default_timezone, roles); escalation->status = ESCALATION_STATUS_COMPLETED; @@ -2864,43 +2939,20 @@ static void service_clean(DB_SERVICE *service) zbx_free(service); } -static void service_rolerule_clean(zbx_service_role_rule_t *rule) +static zbx_hash_t service_role_hash_func(const void *d) { - zbx_free(rule->name); - - if (ZBX_ROLE_RULE_TYPE_STR == rule->type) - zbx_free(rule->value_str); + const zbx_service_role_t *role = (const zbx_service_role_t *)d; - zbx_free(rule); + return ZBX_DEFAULT_UINT64_HASH_FUNC(&role->roleid); } -static void zbx_db_load_service_rules(zbx_vector_service_role_rule_t *rolerules) +static int service_role_compare_func(const void *d1, const void *d2) { - DB_RESULT result; - DB_ROW row; + const zbx_service_role_t *role1 = (const zbx_service_role_t *)d1; + const zbx_service_role_t *role2 = (const zbx_service_role_t *)d2; - result = DBselect("select name,roleid,value_int,value_str,value_serviceid,type from role_rule where name like " - "'services.%%'"); - - while (NULL != (row = DBfetch(result))) - { - zbx_service_role_rule_t *rule = (zbx_service_role_rule_t*)malloc(sizeof(zbx_service_role_rule_t)); - - rule->name = zbx_strdup(NULL, row[0]); - ZBX_STR2UINT64(rule->roleid, row[1]); - ZBX_STR2UINT64(rule->type, row[5]); - - if (ZBX_ROLE_RULE_TYPE_INT == rule->type) - ZBX_STR2UINT64(rule->value_int, row[2]); - else if (ZBX_ROLE_RULE_TYPE_STR == rule->type) - rule->value_str = zbx_strdup(NULL, row[3]); - else if (ZBX_ROLE_RULE_TYPE_SERVICEID == rule->type) - ZBX_STR2UINT64(rule->value_serviceid, row[4]); - - zbx_vector_service_role_rule_append(rolerules, rule); - } - - DBfree_result(result); + ZBX_RETURN_IF_NOT_EQUAL(role1->roleid, role2->roleid); + return 0; } static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *escalations, @@ -2914,7 +2966,7 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc zbx_vector_service_alarm_t service_alarms; zbx_service_alarm_t *service_alarm, service_alarm_local; zbx_vector_service_t services; - zbx_vector_service_role_rule_t rolerules; + zbx_hashset_t service_roles; DB_SERVICE service_local; zbx_vector_uint64_create(&escalationids); @@ -2924,13 +2976,13 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc zbx_vector_uint64_pair_create(&event_pairs); zbx_vector_service_alarm_create(&service_alarms); zbx_vector_service_create(&services); - zbx_vector_service_role_rule_create(&rolerules); + + zbx_hashset_create(&service_roles, 100, service_role_hash_func, service_role_compare_func); add_ack_escalation_r_eventids(escalations, eventids, &event_pairs); get_db_actions_info(actionids, &actions); zbx_db_get_events_by_eventids(eventids, &events); - zbx_db_load_service_rules(&rolerules); if (0 != ((DB_ESCALATION *)escalations->values[0])->serviceid) { @@ -3050,7 +3102,7 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc switch (state) { case ZBX_ESCALATION_CANCEL: - escalation_cancel(escalation, action, event, error, default_timezone, service, &rolerules); + escalation_cancel(escalation, action, event, error, default_timezone, service, &service_roles); zbx_free(error); zbx_vector_uint64_append(&escalationids, escalation->escalationid); continue; @@ -3077,7 +3129,7 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc if (0 != escalation->servicealarmid) { - escalation_update(escalation, action, event, service_alarm, service, default_timezone, &rolerules); + escalation_update(escalation, action, event, service_alarm, service, default_timezone, &service_roles); } else if (0 != escalation->acknowledgeid) { @@ -3100,20 +3152,20 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc } - escalation_acknowledge(escalation, action, event, r_event, default_timezone, &rolerules); + escalation_acknowledge(escalation, action, event, r_event, default_timezone, &service_roles); } else if (NULL != r_event) { if (0 == escalation->esc_step) - escalation_execute(escalation, action, event, service, default_timezone, &rolerules); + escalation_execute(escalation, action, event, service, default_timezone, &service_roles); else - escalation_recover(escalation, action, event, r_event, service, default_timezone, &rolerules); + escalation_recover(escalation, action, event, r_event, service, default_timezone, &service_roles); } else if (escalation->nextcheck <= now) { if (ESCALATION_STATUS_ACTIVE == escalation->status) { - escalation_execute(escalation, action, event, service, default_timezone, &rolerules); + escalation_execute(escalation, action, event, service, default_timezone, &service_roles); } else if (ESCALATION_STATUS_SLEEP == escalation->status) { @@ -3232,8 +3284,8 @@ out: zbx_vector_service_clear_ext(&services, service_clean); zbx_vector_service_destroy(&services); - zbx_vector_service_role_rule_clear_ext(&rolerules, service_rolerule_clean); - zbx_vector_service_role_rule_destroy(&rolerules); + zbx_hashset_clear(&service_roles); + zbx_hashset_destroy(&service_roles); ret = escalationids.values_num; /* performance metric */ diff --git a/src/zabbix_server/service/service_manager.c b/src/zabbix_server/service/service_manager.c index 71cdeef3a51..e92daca0de9 100644 --- a/src/zabbix_server/service/service_manager.c +++ b/src/zabbix_server/service/service_manager.c @@ -2338,8 +2338,7 @@ static void process_rootcause(const zbx_ipc_message_t *message, zbx_service_mana zbx_vector_uint64_destroy(&serviceids); } -static void get_parent_serviceids(unsigned char **data, size_t *data_alloc, size_t *data_offset, - zbx_service_t *service) +static void get_parent_serviceids(zbx_service_t *service, zbx_vector_uint64_t *parentids) { zbx_uint64_t i; @@ -2348,9 +2347,10 @@ static void get_parent_serviceids(unsigned char **data, size_t *data_alloc, size zbx_service_t *parent; parent = (zbx_service_t*)(service->parents.values[i]); - zbx_service_serialize_id(data, data_alloc, data_offset, parent->serviceid); - get_parent_serviceids(data, data_alloc, data_offset, parent); + zbx_vector_uint64_append(parentids, parent->serviceid); + + get_parent_serviceids(parent, parentids); } } @@ -2358,19 +2358,30 @@ static void process_parentlist(const zbx_ipc_message_t *message, zbx_service_man zbx_ipc_client_t *client) { unsigned char *data = NULL; - size_t data_alloc = 0, data_offset = 0; + zbx_uint32_t data_alloc = 0, data_offset = 0; zbx_uint64_t child_serviceid = 0; zbx_service_t *service, service_local; + zbx_vector_uint64_t parentids; zbx_deserialize_uint64(message->data, &child_serviceid); service_local.serviceid = child_serviceid; + zbx_vector_uint64_create(&parentids); + if (NULL != (service = zbx_hashset_search(&service_manager->services, &service_local))) - get_parent_serviceids(&data, &data_alloc, &data_offset, service); + { + get_parent_serviceids(service, &parentids); + + zbx_vector_uint64_sort(&parentids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_uniq(&parentids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + zbx_service_serialize_parentids(&data, &data_alloc, &data_offset, &parentids); + } zbx_ipc_client_send(client, ZBX_IPC_SERVICE_SERVICE_PARENT_LIST, data, data_offset); + zbx_vector_uint64_destroy(&parentids); zbx_free(data); } |