diff options
-rw-r--r-- | include/db.h | 1 | ||||
-rw-r--r-- | include/service_protocol.h | 7 | ||||
-rw-r--r-- | src/libs/zbxdbupgrade/dbupgrade_5050.c | 38 | ||||
-rw-r--r-- | src/libs/zbxservice/service_protocol.c | 90 | ||||
-rw-r--r-- | src/zabbix_server/escalator/escalator.c | 437 | ||||
-rw-r--r-- | src/zabbix_server/service/service_manager.c | 40 |
6 files changed, 307 insertions, 306 deletions
diff --git a/include/db.h b/include/db.h index 6fa39c30b37..cb1a635423f 100644 --- a/include/db.h +++ b/include/db.h @@ -345,6 +345,7 @@ typedef struct char *name; zbx_vector_uint64_t eventids; zbx_vector_ptr_t events; + zbx_vector_ptr_t service_tags; } DB_SERVICE; diff --git a/include/service_protocol.h b/include/service_protocol.h index 2a134a40af7..97520a8608e 100644 --- a/include/service_protocol.h +++ b/include/service_protocol.h @@ -29,13 +29,6 @@ #include "zbxalgo.h" #include "zbxservice.h" -typedef struct -{ - zbx_uint64_t serviceid; - zbx_vector_tags_t tags; -} -zbx_parent_service_t; - void zbx_service_serialize(unsigned char **data, size_t *data_alloc, size_t *data_offset, zbx_uint64_t eventid, int clock, int ns, int value, int severity, const zbx_vector_ptr_t *tags); void zbx_service_deserialize(const unsigned char *data, zbx_uint32_t size, zbx_vector_ptr_t *events); diff --git a/src/libs/zbxdbupgrade/dbupgrade_5050.c b/src/libs/zbxdbupgrade/dbupgrade_5050.c index 727c1d07ae6..22a6f2ba5be 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_5050.c +++ b/src/libs/zbxdbupgrade/dbupgrade_5050.c @@ -509,42 +509,10 @@ static int DBpatch_5050037(void) static int DBpatch_5050038(void) { - DB_RESULT result; - DB_ROW row; - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - int ret = FAIL; - - if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER)) - return SUCCEED; - - result = DBselect("select role_ruleid,name from role_rule where name='actions.manage_services'"); - - DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); - - while (NULL != (row = DBfetch(result))) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update role_rule set name='services.write' where " - "role_ruleid=%s;\n", row[0]); - - if (SUCCEED != (ret = DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset))) - goto out; - } - - DBend_multiple_update(&sql, &sql_alloc, &sql_offset); - - if (16 < sql_offset) - { - if (ZBX_DB_OK > DBexecute("%s", sql)) - goto out; - } - - ret = SUCCEED; -out: - DBfree_result(result); - zbx_free(sql); + if (ZBX_DB_OK > DBexecute("update role_rule set name='services.write' where name='actions.manage_services'")) + return FAIL; - return ret; + return SUCCEED; } #endif diff --git a/src/libs/zbxservice/service_protocol.c b/src/libs/zbxservice/service_protocol.c index 9b856346b67..214001aaec0 100644 --- a/src/libs/zbxservice/service_protocol.c +++ b/src/libs/zbxservice/service_protocol.c @@ -311,93 +311,3 @@ void zbx_service_deserialize_rootcause(const unsigned char *data, zbx_uint32_t s } } } - -void zbx_service_serialize_parent_service(unsigned char **data, size_t *data_alloc, size_t *data_offset, - zbx_uint64_t serviceid, zbx_vector_tags_t *tags) -{ - zbx_uint32_t data_len = 0, *len = NULL; - zbx_uint32_t i, tags_num; - unsigned char *ptr; - zbx_tag_t *tag = NULL; - zbx_hashset_iter_t iter; - - zbx_serialize_prepare_value(data_len, serviceid); - - tags_num = (zbx_uint32_t)tags->values_num; - zbx_serialize_prepare_value(data_len, tags_num); - - len = (zbx_uint32_t *)zbx_malloc(NULL, sizeof(zbx_uint32_t) * 2 * (size_t)tags->values_num); - - if (0 != tags->values_num) - { - for (i = 0; i < tags->values_num; i++) - { - tag = tags->values[i]; - zbx_serialize_prepare_str_len(data_len, tag->tag, len[i * 2]); - zbx_serialize_prepare_str_len(data_len, ZBX_NULL2EMPTY_STR(tag->value), len[i * 2 + 1]); - } - } - - 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, serviceid); - ptr += zbx_serialize_value(ptr, tags_num); - - for (i = 0; i < tags->values_num; i++) - { - tag = tags->values[i]; - - ptr += zbx_serialize_str(ptr, tag->tag, len[i * 2]); - ptr += zbx_serialize_str(ptr, ZBX_NULL2EMPTY_STR(tag->value), len[i * 2 + 1]); - } - -} - -void zbx_service_deserialize_parent_services(const unsigned char *data, zbx_uint32_t size, zbx_vector_ptr_t *parent_services) -{ - const unsigned char *end = data + size; - - while (data < end) - { - zbx_parent_service_t *service; - zbx_uint32_t values_num, i; - - service = (zbx_parent_service_t *)zbx_malloc(NULL, sizeof(zbx_parent_service_t)); - zbx_vector_tags_create(&service->tags); - - data += zbx_deserialize_value(data, &service->serviceid); - data += zbx_deserialize_value(data, &values_num); - - if (0 != values_num) - { - zbx_vector_tags_reserve(&service->tags, (size_t)values_num); - - for (i = 0; i < values_num; i++) - { - zbx_tag_t *tag; - zbx_uint32_t len; - - tag = (zbx_tag_t *)zbx_malloc(NULL, sizeof(zbx_tag_t)); - data += zbx_deserialize_str(data, &tag->tag, len); - data += zbx_deserialize_str(data, &tag->value, len); - - zbx_vector_tags_append(&service->tags, tag); - } - } - zbx_vector_ptr_append(parent_services, service); - } - -} - diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c index ce86d6a5c89..35ee5857d3a 100644 --- a/src/zabbix_server/escalator/escalator.c +++ b/src/zabbix_server/escalator/escalator.c @@ -60,6 +60,10 @@ extern int CONFIG_ESCALATOR_FORKS; #define ZBX_ALERT_MESSAGE_ERR_USR 1 #define ZBX_ALERT_MESSAGE_ERR_MSG 2 +#define ZBX_ROLE_RULE_TYPE_INT 0 +#define ZBX_ROLE_RULE_TYPE_STR 1 +#define ZBX_ROLE_RULE_TYPE_SERVICEID 3 + typedef struct { zbx_uint64_t userid; @@ -80,9 +84,32 @@ typedef struct } zbx_tag_filter_t; +typedef struct +{ + char *read_tag; + char *read_value; + char *write_tag; + char *write_value; +} +zbx_service_tag_rule_t; + +typedef struct +{ + zbx_uint64_t roleid; + char *name; + int type; + zbx_uint64_t value_serviceid; + char *value_str; + zbx_uint64_t value_int; +} +zbx_service_role_rule_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, @@ -375,74 +402,156 @@ out: return perm; } -static int get_service_global_access_rights(zbx_uint64_t roleid, zbx_uint64_t serviceid) +static int get_service_global_rights_enabled(zbx_uint64_t roleid, zbx_vector_service_role_rule_t *rolerules) { - DB_RESULT result; - DB_ROW row; - int ret = PERM_READ_WRITE; + int i; - result = DBselect("select name,value_int from role_rule where name in ('services.read','services.write') and " - "roleid=" ZBX_FS_UI64, roleid); + for (i = 0; i < rolerules->values_num; i++) + { + zbx_service_role_rule_t *rule; - while (NULL != (row = DBfetch(result))) + 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; + } + } + + return FAIL; +} + +static void check_cached_rule_serviceids(zbx_uint64_t roleid, zbx_uint64_t serviceid, + zbx_vector_service_role_rule_t *rolerules, int *perm) +{ + int i; + + for (i = 0; i < rolerules->values_num; i++) + { + zbx_service_role_rule_t *rule; + + rule = rolerules->values[i]; + + if (ZBX_ROLE_RULE_TYPE_SERVICEID != rule->type) + continue; + + if (roleid == rule->roleid && serviceid == rule->value_serviceid) + { + 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; + } + } +} + +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; + + for (i = 0; i < rolerules->values_num; i++) + { + zbx_service_role_rule_t *rule; + + rule = rolerules->values[i]; + + if (ZBX_ROLE_RULE_TYPE_STR != rule->type || rule->roleid != roleid) + continue; + + 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; + } + + for (i = 0; i < service_tags->values_num; i++) { - zbx_uint64_t value; + zbx_tag_t *tag; - ZBX_STR2UINT64(value, row[1]); + tag = (zbx_tag_t*)service_tags->values[i]; - if (0 == value) + if (NULL != tag_rules->read_tag) { - if (0 == strcmp(row[0], "services.read")) + if (0 == strcmp(tag_rules->read_tag, tag->tag)) { - ret = PERM_DENY; - goto out; + if (NULL == tag_rules->read_value || 0 == strcmp(tag_rules->read_value, tag->value)) + *perm |= PERM_READ; } - else + } + + if (NULL != tag_rules->write_tag) + { + if (0 == strcmp(tag_rules->write_tag, tag->tag)) { - ret = PERM_READ; + if (NULL == tag_rules->write_value || 0 == strcmp(tag_rules->write_value, tag->value)) + { + *perm |= PERM_READ_WRITE; + } } } } +} -out: - DBfree_result(result); +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; - return ret; + for (i = 0; i < parent_ids->values_num; i++) + { + zbx_uint64_t parent_id; + + parent_id = parent_ids->values[i]; + check_cached_rule_serviceids(roleid, parent_id, rolerules, perm); + } } -static int get_service_access_rights(zbx_uint64_t roleid, zbx_uint64_t serviceid) +static void check_db_parent_rule_tag_match(zbx_vector_uint64_t *parent_ids, + zbx_service_tag_rule_t *tag_rules, int *perm) { DB_RESULT result; DB_ROW row; - int ret = 0, rows = 0; + char *serviceid_sql = NULL, *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0, serviceid_sql_alloc = 0, serviceid_sql_offset = 0; - result = DBselect("select name,value_serviceid from role_rule where roleid=" ZBX_FS_UI64 " and value_serviceid=" - ZBX_FS_UI64 " and type=3", roleid, serviceid); + if (0 == parent_ids->values_num || NULL == tag_rules->read_tag && NULL == tag_rules->write_tag) + return; - while (NULL != (row = DBfetch(result))) - { - zbx_uint64_t value; + DBadd_condition_alloc(&serviceid_sql, &serviceid_sql_alloc, &serviceid_sql_offset, "serviceid", parent_ids->values, + parent_ids->values_num); - ZBX_STR2UINT64(value, row[1]); + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select null from service_tag where%s and (", serviceid_sql); - if (0 == strncmp(row[0], "services.read.id", ZBX_CONST_STRLEN("services.read.id"))) - { - ret |= PERM_READ; - } - else if (0 == strncmp(row[0], "services.write.id", ZBX_CONST_STRLEN("services.write.id"))) - { - ret |= PERM_READ_WRITE; - } + 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); + } - rows++; + 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 (0 == rows) - ret = PERM_READ_WRITE; + result = DBselect("%s) limit 1", sql); - DBfree_result(result); + if (NULL != (row = DBfetch(result))) + { + *perm |= PERM_READ; + } - return ret; + DBfree_result(result); } /****************************************************************************** @@ -455,94 +564,53 @@ static int get_service_access_rights(zbx_uint64_t roleid, zbx_uint64_t serviceid * or permission otherwise * * * ******************************************************************************/ -static int get_service_permission(zbx_uint64_t userid, char **user_timezone, zbx_uint64_t serviceid) +static int get_service_permission(zbx_uint64_t userid, char **user_timezone, const DB_SERVICE *service, + zbx_vector_service_role_rule_t *rolerules) { - int i, perm; + int perm = PERM_DENY; unsigned char *data = NULL; size_t data_alloc = 0, data_offset = 0; zbx_user_t user = {.userid = userid}; zbx_ipc_message_t response; - zbx_vector_ptr_t parent_services; + zbx_vector_uint64_t parent_ids; + zbx_service_tag_rule_t tag_rules = { 0 }; user.type = get_user_info(userid, &user.roleid, user_timezone); - if (PERM_DENY == (perm = get_service_global_access_rights(user.roleid, serviceid))) + // 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 (PERM_DENY == (perm = get_service_access_rights(user.roleid, serviceid))) + // read read/write rule rights + check_cached_rule_serviceids(user.roleid, service->serviceid, rolerules, &perm); + if (perm > PERM_DENY) return perm; - zbx_service_serialize_id(&data, &data_alloc, &data_offset, serviceid); + // 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) + return perm; - if (NULL == data) - return PERM_DENY; + // get service parent ids from service manager + zbx_service_serialize_id(&data, &data_alloc, &data_offset, service->serviceid); - zbx_vector_ptr_create(&parent_services); + if (NULL == data) + goto out; zbx_ipc_message_init(&response); zbx_service_send(ZBX_IPC_SERVICE_SERVICE_PARENT_LIST, data, data_offset, &response); - zbx_service_deserialize_parent_services(response.data, response.size, &parent_services); + zbx_vector_uint64_create(&parent_ids); + zbx_service_deserialize_ids(response.data, response.size, &parent_ids); zbx_ipc_message_clean(&response); - for (i = 0; i < parent_services.values_num; i++) - { - int j; - zbx_parent_service_t *ps = (zbx_parent_service_t*)(parent_services.values[i]); - - if (PERM_DENY == (perm = get_service_access_rights(user.roleid, ps->serviceid))) - goto out; - - for (j = 0; i < ps->tags.values_num; i++) - { - zbx_tag_t *tag = ps->tags.values[i]; - DB_ROW row; - DB_RESULT result; - char *tag_read, *tag_write, *value_read, *value_write; - - result = DBselect("select r.name,r.value_str from role_rule r inner join service_tag s where " - "(r.value_str=s.tag or r.value_str=s.value) and r.name in ('services.read.tag.name', " - "'services.read.tag.value') and r.type=1"); - - tag_read = tag_write = value_read = value_write = NULL; - - while (NULL != (row = DBfetch(result))) - { - if (0 == strcmp("services.read.tag.name", row[0])) - tag_read = zbx_strdup(NULL, row[1]); - else if (0 == strcmp("services.read.tag.value", row[0])) - value_read = zbx_strdup(NULL, row[1]); - if (0 == strcmp("services.write.tag.name", row[0])) - tag_write = zbx_strdup(NULL, row[1]); - else if (0 == strcmp("services.write.tag.value", row[0])) - value_write = zbx_strdup(NULL, row[1]); - } - DBfree_result(result); - - if (NULL != tag_read) - { - if ((NULL != value_read && 0 == strcmp(tag_read, tag->tag) && 0 == strcmp(value_read, tag->value)) || - (0 == strcmp(tag_read, tag->tag))) - { - perm |= PERM_READ; - } - } - if (NULL != tag_write) - { - if ((NULL != value_write && 0 == strcmp(tag_write, tag->tag) && 0 == strcmp(value_write, tag->value)) || - (0 == strcmp(tag_write, tag->tag))) - { - perm |= PERM_READ_WRITE; - } - } - - zbx_free(tag_read); - zbx_free(tag_write); - zbx_free(value_read); - zbx_free(value_write); - } - } + // 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) + return perm; + check_db_parent_rule_tag_match(&parent_ids, &tag_rules, &perm); out: + zbx_vector_uint64_destroy(&parent_ids); zbx_free(data); return perm; @@ -722,7 +790,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) + unsigned char evt_src, unsigned char op_mode, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) { DB_RESULT result; DB_ROW row; @@ -766,7 +834,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, event->objectid)) + if (PERM_READ > get_service_permission(userid, &user_timezone, service, rolerules)) goto clean; break; default: @@ -805,7 +873,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) + const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) { char *sql = NULL; DB_RESULT result; @@ -868,7 +936,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, event->objectid)) + if (PERM_READ > get_service_permission(userid, &user_timezone, service, rolerules)) goto clean; break; default: @@ -904,7 +972,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 char *error, const char *default_timezone, const DB_SERVICE *service, zbx_vector_service_role_rule_t *rolerules) { char *message_dyn, *sql = NULL; DB_RESULT result; @@ -959,7 +1027,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, event->objectid)) + if (PERM_READ > get_service_permission(userid, &user_timezone, service, rolerules)) goto clean; break; default: @@ -1768,7 +1836,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) + const DB_SERVICE *service, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) { DB_RESULT result; DB_ROW row; @@ -1827,7 +1895,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); + ZBX_OPERATION_MODE_NORMAL, default_timezone, rolerules); break; case OPERATION_TYPE_COMMAND: execute_commands(event, NULL, NULL, NULL, service, action->actionid, operationid, @@ -1895,7 +1963,8 @@ 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) + const DB_ACTION *action, const DB_SERVICE *service, const char *default_timezone, + zbx_vector_service_role_rule_t *rolerules) { DB_RESULT result; DB_ROW row; @@ -1925,12 +1994,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); + ZBX_OPERATION_MODE_RECOVERY, default_timezone, rolerules); 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); + default_timezone, rolerules); break; case OPERATION_TYPE_COMMAND: execute_commands(event, r_event, NULL, NULL, service, action->actionid, operationid, 1, @@ -1962,7 +2031,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) + const DB_SERVICE *service, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) { DB_RESULT result; DB_ROW row; @@ -1992,12 +2061,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); + ZBX_OPERATION_MODE_UPDATE, default_timezone, rolerules); 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); + default_timezone, rolerules); if (NULL != ack) { add_sentusers_ack_msg(&user_msg, action->actionid, operationid, event, r_event, @@ -2333,7 +2402,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 char *error, const char *default_timezone, const DB_SERVICE *service, zbx_vector_service_role_rule_t *rolerules) { ZBX_USER_MSG *user_msg = NULL; @@ -2344,7 +2413,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); + default_timezone, service, rolerules); flush_user_msg(&user_msg, escalation->esc_step, event, NULL, action->actionid, NULL, NULL, NULL); } @@ -2366,12 +2435,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) + const DB_SERVICE *service, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) { 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); + escalation_execute_operations(escalation, event, action, service, default_timezone, rolerules); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } @@ -2389,12 +2458,13 @@ 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) + const DB_EVENT *r_event, const DB_SERVICE *service, const char *default_timezone, + zbx_vector_service_role_rule_t *rolerules) { 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); + escalation_execute_recovery_operations(event, r_event, action, service, default_timezone, rolerules); escalation->status = ESCALATION_STATUS_COMPLETED; @@ -2414,7 +2484,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) + const DB_EVENT *r_event, const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) { DB_ROW row; DB_RESULT result; @@ -2440,7 +2510,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); + escalation_execute_update_operations(event, r_event, action, &ack, NULL, NULL, default_timezone, rolerules); } DBfree_result(result); @@ -2466,13 +2536,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) + const char *default_timezone, zbx_vector_service_role_rule_t *rolerules) { 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); + escalation_execute_update_operations(event, NULL, action, NULL, service_alarm, service, default_timezone, rolerules); escalation->status = ESCALATION_STATUS_COMPLETED; @@ -2611,6 +2681,7 @@ static void db_get_services(const zbx_vector_ptr_t *escalations, zbx_vector_serv size_t sql_alloc = 0, sql_offset = 0; zbx_vector_uint64_t serviceids, eventids; int i, j, index; + zbx_int64_t last_serviceid = -1; zbx_vector_uint64_create(&serviceids); zbx_vector_uint64_create(&eventids); @@ -2630,29 +2701,62 @@ static void db_get_services(const zbx_vector_ptr_t *escalations, zbx_vector_serv zbx_vector_uint64_sort(&serviceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_vector_uint64_uniq(&serviceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "serviceid", serviceids.values, + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.serviceid", serviceids.values, serviceids.values_num); result = DBselect( - "select serviceid,name" - " from services" - " where%s order by serviceid", + "select s.serviceid,s.name,st.tag,st.value" + " from services s left join service_tag st on s.serviceid=st.serviceid" + " where%s order by s.serviceid", sql); while (NULL != (row = DBfetch(result))) { DB_SERVICE *service; + zbx_uint64_t serviceid; + + ZBX_STR2UINT64(serviceid, row[0]); + + if ((zbx_int64_t)serviceid == last_serviceid) + { + DB_SERVICE *last_service; + zbx_tag_t *tag = zbx_malloc(NULL, sizeof(zbx_tag_t)); + + last_service = services->values[services->values_num - 1]; + + tag->tag = zbx_strdup(NULL, row[2]); + tag->value = zbx_strdup(NULL, row[3]); + + zbx_vector_ptr_append(&last_service->service_tags, tag); + continue; + } service = zbx_malloc(NULL, sizeof(DB_SERVICE)); - ZBX_STR2UINT64(service->serviceid, row[0]); + service->serviceid = serviceid; service->name = zbx_strdup(NULL, row[1]); zbx_vector_uint64_create(&service->eventids); zbx_vector_ptr_create(&service->events); + if (NULL != row[2]) + { + zbx_tag_t *tag = zbx_malloc(NULL, sizeof(zbx_tag_t)); + zbx_vector_ptr_create(&service->service_tags); + + tag->tag = zbx_strdup(NULL, row[2]); + + if (NULL == row[3]) + tag->value = zbx_strdup(NULL, row[3]); + else + tag->value = '\0'; + + zbx_vector_ptr_append(&service->service_tags, tag); + } + zbx_vector_service_append(services, service); + + last_serviceid = (zbx_int64_t)service->serviceid; } DBfree_result(result); - zbx_free(sql); get_services_rootcause_eventids(&serviceids, services); @@ -2760,6 +2864,45 @@ static void service_clean(DB_SERVICE *service) zbx_free(service); } +static void service_rolerule_clean(zbx_service_role_rule_t *rule) +{ + zbx_free(rule->name); + + if (ZBX_ROLE_RULE_TYPE_STR == rule->type) + zbx_free(rule->value_str); + + zbx_free(rule); +} + +static void zbx_db_load_service_rules(zbx_vector_service_role_rule_t *rolerules) +{ + DB_RESULT result; + DB_ROW row; + + 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); +} + static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *escalations, zbx_vector_uint64_t *eventids, zbx_vector_uint64_t *actionids, const char *default_timezone) { @@ -2771,6 +2914,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; DB_SERVICE service_local; zbx_vector_uint64_create(&escalationids); @@ -2780,11 +2924,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); 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) { @@ -2904,7 +3050,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); + escalation_cancel(escalation, action, event, error, default_timezone, service, &rolerules); zbx_free(error); zbx_vector_uint64_append(&escalationids, escalation->escalationid); continue; @@ -2931,7 +3077,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); + escalation_update(escalation, action, event, service_alarm, service, default_timezone, &rolerules); } else if (0 != escalation->acknowledgeid) { @@ -2954,20 +3100,20 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc } - escalation_acknowledge(escalation, action, event, r_event, default_timezone); + escalation_acknowledge(escalation, action, event, r_event, default_timezone, &rolerules); } else if (NULL != r_event) { if (0 == escalation->esc_step) - escalation_execute(escalation, action, event, service, default_timezone); + escalation_execute(escalation, action, event, service, default_timezone, &rolerules); else - escalation_recover(escalation, action, event, r_event, service, default_timezone); + escalation_recover(escalation, action, event, r_event, service, default_timezone, &rolerules); } else if (escalation->nextcheck <= now) { if (ESCALATION_STATUS_ACTIVE == escalation->status) { - escalation_execute(escalation, action, event, service, default_timezone); + escalation_execute(escalation, action, event, service, default_timezone, &rolerules); } else if (ESCALATION_STATUS_SLEEP == escalation->status) { @@ -3086,6 +3232,9 @@ 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); + ret = escalationids.values_num; /* performance metric */ zbx_vector_uint64_destroy(&escalationids); @@ -3124,8 +3273,8 @@ static int process_escalations(int now, int *nextcheck, unsigned int escalation_ char *filter = NULL; size_t filter_alloc = 0, filter_offset = 0; - zbx_vector_ptr_t escalations; - zbx_vector_uint64_t actionids, eventids; + zbx_vector_ptr_t escalations; + zbx_vector_uint64_t actionids, eventids; DB_ESCALATION *escalation; diff --git a/src/zabbix_server/service/service_manager.c b/src/zabbix_server/service/service_manager.c index 92e4edabb44..71cdeef3a51 100644 --- a/src/zabbix_server/service/service_manager.c +++ b/src/zabbix_server/service/service_manager.c @@ -2338,33 +2338,19 @@ static void process_rootcause(const zbx_ipc_message_t *message, zbx_service_mana zbx_vector_uint64_destroy(&serviceids); } -static void get_parent_service_tags(unsigned char **data, size_t *data_alloc, size_t *data_offset, - zbx_service_t *service, zbx_vector_tags_t *tags) +static void get_parent_serviceids(unsigned char **data, size_t *data_alloc, size_t *data_offset, + zbx_service_t *service) { - int i; - - if (NULL == service) - return; + zbx_uint64_t i; for (i = 0; i < service->parents.values_num; i++) { - int j; zbx_service_t *parent; - parent = (zbx_service_t *)(service->parents.values[i]); - - for (j = 0; j < parent->tags.values_num; j++) - { - zbx_service_tag_t *stag = parent->tags.values[j]; - zbx_tag_t *tag = (zbx_tag_t*)malloc(sizeof(zbx_tag_t)); - tag->tag = zbx_strdup(NULL, stag->name); - tag->value = zbx_strdup(NULL, stag->value); - zbx_vector_tags_append(tags, tag); - } - - get_parent_service_tags(data, data_alloc, data_offset, (zbx_service_t*)parent->parents.values[j], tags); + parent = (zbx_service_t*)(service->parents.values[i]); + zbx_service_serialize_id(data, data_alloc, data_offset, parent->serviceid); - zbx_service_serialize_parent_service(data, data_alloc, data_offset, parent->serviceid, tags); + get_parent_serviceids(data, data_alloc, data_offset, parent); } } @@ -2372,26 +2358,20 @@ 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; + size_t data_alloc = 0, data_offset = 0; zbx_uint64_t child_serviceid = 0; - zbx_service_t *service, service_local, *parent_service = NULL; - zbx_vector_tags_t tags; + zbx_service_t *service, service_local; zbx_deserialize_uint64(message->data, &child_serviceid); service_local.serviceid = child_serviceid; - if (NULL == (service = zbx_hashset_search(&service_manager->services, &service_local))) - return; - - zbx_vector_tags_create(&tags); - get_parent_service_tags(&data, &data_alloc, &data_offset, service, &tags); + if (NULL != (service = zbx_hashset_search(&service_manager->services, &service_local))) + get_parent_serviceids(&data, &data_alloc, &data_offset, service); zbx_ipc_client_send(client, ZBX_IPC_SERVICE_SERVICE_PARENT_LIST, data, data_offset); zbx_free(data); - zbx_vector_tags_clear(&tags); - zbx_vector_tags_destroy(&tags); } static void service_manager_init(zbx_service_manager_t *service_manager) |