Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/db.h1
-rw-r--r--include/service_protocol.h7
-rw-r--r--src/libs/zbxdbupgrade/dbupgrade_5050.c38
-rw-r--r--src/libs/zbxservice/service_protocol.c90
-rw-r--r--src/zabbix_server/escalator/escalator.c437
-rw-r--r--src/zabbix_server/service/service_manager.c40
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)