/****************************************************************************** * * * Function: DBcopy_template_items * * * * Purpose: copy template items to host * * * * Parameters: hostid - [IN] host id * * templateids - [IN] array of template IDs * * * ******************************************************************************/ void DBcopy_template_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids) { const char *__function_name = "DBcopy_template_items"; zbx_vector_ptr_t items, lld_rules; int new_conditions = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); zbx_vector_ptr_create(&items); zbx_vector_ptr_create(&lld_rules); get_template_items(hostid, templateids, &items); if (0 == items.values_num) goto out; get_template_lld_rule_map(&items, &lld_rules); new_conditions = calculate_template_lld_rule_conditionids(&lld_rules); update_template_lld_rule_formulas(&items, &lld_rules); save_template_items(hostid, &items); save_template_lld_rules(&items, &lld_rules, new_conditions); save_template_item_applications(&items); save_template_discovery_prototypes(hostid, &items); out: zbx_vector_ptr_clear_ext(&lld_rules, (zbx_clean_func_t)free_lld_rule_map); zbx_vector_ptr_destroy(&lld_rules); zbx_vector_ptr_clear_ext(&items, (zbx_clean_func_t)free_template_item); zbx_vector_ptr_destroy(&items); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: free_lld_rule_map * * * * Purpose: frees lld rule mapping * * * * Parameters: item - [IN] the lld rule mapping * * * ******************************************************************************/ void free_lld_rule_map(zbx_lld_rule_map_t *rule) { zbx_vector_ptr_clear_ext(&rule->conditions, (zbx_clean_func_t)free_lld_rule_condition); zbx_vector_ptr_destroy(&rule->conditions); zbx_vector_uint64_destroy(&rule->conditionids); zbx_free(rule); }
/****************************************************************************** * * * Function: db_update_host_maintenances * * * * Purpose: update host maintenance parameters in cache and database * * * ******************************************************************************/ static int update_host_maintenances(void) { zbx_vector_uint64_t maintenanceids; zbx_vector_ptr_t updates; int hosts_num = 0; int tnx_error; zbx_vector_uint64_create(&maintenanceids); zbx_vector_ptr_create(&updates); zbx_vector_ptr_reserve(&updates, 100); do { DBbegin(); if (SUCCEED == zbx_dc_get_running_maintenanceids(&maintenanceids)) zbx_db_lock_maintenanceids(&maintenanceids); /* host maintenance update must be called even with no maintenances running */ /* to reset host maintenance status if necessary */ zbx_dc_get_host_maintenance_updates(&maintenanceids, &updates); if (0 != updates.values_num) db_update_host_maintenances(&updates); if (ZBX_DB_OK == (tnx_error = DBcommit()) && 0 != (hosts_num = updates.values_num)) zbx_dc_flush_host_maintenance_updates(&updates); zbx_vector_ptr_clear_ext(&updates, (zbx_clean_func_t)zbx_ptr_free); zbx_vector_uint64_clear(&maintenanceids); } while (ZBX_DB_DOWN == tnx_error); zbx_vector_ptr_destroy(&updates); zbx_vector_uint64_destroy(&maintenanceids); return hosts_num; }
/****************************************************************************** * * * Function: save_template_discovery_prototypes * * * * Purpose: saves host item prototypes in database * * * * Parameters: hostid - [IN] the target host * * items - [IN] the template items * * * ******************************************************************************/ void save_template_discovery_prototypes(zbx_uint64_t hostid, zbx_vector_ptr_t *items) { typedef struct { zbx_uint64_t itemid; zbx_uint64_t parent_itemid; } zbx_proto_t; DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_vector_uint64_t itemids; zbx_vector_ptr_t prototypes; zbx_proto_t *proto; int i; zbx_db_insert_t db_insert; zbx_vector_ptr_create(&prototypes); zbx_vector_uint64_create(&itemids); for (i = 0; i < items->values_num; i++) { zbx_template_item_t *item = items->values[i]; /* process only new prototype items */ if (NULL == item->key || 0 == (ZBX_FLAG_DISCOVERY_PROTOTYPE & item->flags)) continue; zbx_vector_uint64_append(&itemids, item->itemid); } if (0 == itemids.values_num) goto out; zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select i.itemid,r.itemid" " from items i,item_discovery id,items r" " where i.templateid=id.itemid" " and id.parent_itemid=r.templateid" " and r.hostid=" ZBX_FS_UI64 " and", hostid); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid", itemids.values, itemids.values_num); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { proto = zbx_malloc(NULL, sizeof(zbx_proto_t)); ZBX_STR2UINT64(proto->itemid, row[0]); ZBX_STR2UINT64(proto->parent_itemid, row[1]); zbx_vector_ptr_append(&prototypes, proto); } DBfree_result(result); if (0 == prototypes.values_num) goto out; zbx_db_insert_prepare(&db_insert, "item_discovery", "itemdiscoveryid", "itemid", "parent_itemid", NULL); for (i = 0; i < prototypes.values_num; i++) { proto = prototypes.values[i]; zbx_db_insert_add_values(&db_insert, __UINT64_C(0), proto->itemid, proto->parent_itemid); } zbx_db_insert_autoincrement(&db_insert, "itemdiscoveryid"); zbx_db_insert_execute(&db_insert); zbx_db_insert_clean(&db_insert); out: zbx_free(sql); zbx_vector_uint64_destroy(&itemids); zbx_vector_ptr_clear_ext(&prototypes, zbx_ptr_free); zbx_vector_ptr_destroy(&prototypes); }
/****************************************************************************** * * * Function: save_template_item_applications * * * * Purpose: saves new item applications links in database * * * * Parameters: items - [IN] the template items * * * ******************************************************************************/ void save_template_item_applications(zbx_vector_ptr_t *items) { typedef struct { zbx_uint64_t itemid; zbx_uint64_t applicationid; } zbx_itemapp_t; DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_vector_uint64_t itemids; zbx_vector_ptr_t itemapps; zbx_itemapp_t *itemapp; int i; zbx_db_insert_t db_insert; zbx_vector_ptr_create(&itemapps); zbx_vector_uint64_create(&itemids); for (i = 0; i < items->values_num; i++) { zbx_template_item_t *item = items->values[i]; zbx_vector_uint64_append(&itemids, item->itemid); } zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select hi.itemid,ha.applicationid" " from items_applications tia" " join items hi on hi.templateid=tia.itemid" " and"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hi.itemid", itemids.values, itemids.values_num); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " join application_template hat on hat.templateid=tia.applicationid" " join applications ha on ha.applicationid=hat.applicationid" " and ha.hostid=hi.hostid" " left join items_applications hia on hia.applicationid=ha.applicationid" " and hia.itemid=hi.itemid" " where hia.itemappid is null"); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { itemapp = zbx_malloc(NULL, sizeof(zbx_itemapp_t)); ZBX_STR2UINT64(itemapp->itemid, row[0]); ZBX_STR2UINT64(itemapp->applicationid, row[1]); zbx_vector_ptr_append(&itemapps, itemapp); } DBfree_result(result); if (0 == itemapps.values_num) goto out; zbx_db_insert_prepare(&db_insert, "items_applications", "itemappid", "itemid", "applicationid", NULL); for (i = 0; i < itemapps.values_num; i++) { itemapp = itemapps.values[i]; zbx_db_insert_add_values(&db_insert, __UINT64_C(0), itemapp->itemid, itemapp->applicationid); } zbx_db_insert_autoincrement(&db_insert, "itemappid"); zbx_db_insert_execute(&db_insert); zbx_db_insert_clean(&db_insert); out: zbx_free(sql); zbx_vector_uint64_destroy(&itemids); zbx_vector_ptr_clear_ext(&itemapps, zbx_ptr_free); zbx_vector_ptr_destroy(&itemapps); }
/****************************************************************************** * * * Function: zbx_procstat_collect * * * * Purpose: performs process statistics collection * * * ******************************************************************************/ void zbx_procstat_collect() { /* identifies current collection iteration */ static int runid = 1; /* number of (non-unique) pids that match queries */ int pids_num = 0; /* flags specifying what process properties must be retrieved */ int flags; /* local, working copy of queries */ zbx_vector_ptr_t queries; /* data about all processes on system */ zbx_vector_ptr_t processes; /* pids (unique) for which to collect data in this iteration */ zbx_vector_uint64_t pids; /* current reading of the per-pid cpu usage statistics (array, items correspond to pids) */ zbx_procstat_util_t *stats; /* time of the per-pid usage statistics collection */ zbx_timespec_t snapshot_timestamp; if (FAIL == zbx_procstat_collector_started() || FAIL == procstat_running()) goto out; zbx_vector_ptr_create(&queries); zbx_vector_ptr_create(&processes); zbx_vector_uint64_create(&pids); if (ZBX_SYSINFO_PROC_NONE == (flags = procstat_build_local_query_vector(&queries, runid))) goto clean; if (SUCCEED != zbx_proc_get_processes(&processes, flags)) goto clean; pids_num = procstat_scan_query_pids(&queries, &processes); procstat_get_monitored_pids(&pids, &queries, pids_num); stats = (zbx_procstat_util_t *)zbx_malloc(NULL, sizeof(zbx_procstat_util_t) * pids.values_num); snapshot_timestamp = procstat_get_cpu_util_snapshot_for_pids(stats, &pids); procstat_calculate_cpu_util_for_queries(&queries, &pids, stats); procstat_update_query_statistics(&queries, runid, &snapshot_timestamp); /* replace the current snapshot with the new stats */ zbx_free(procstat_snapshot); procstat_snapshot = stats; procstat_snapshot_num = pids.values_num; clean: zbx_vector_uint64_destroy(&pids); zbx_proc_free_processes(&processes); zbx_vector_ptr_destroy(&processes); zbx_vector_ptr_clear_ext(&queries, (zbx_mem_free_func_t)procstat_free_query_data); zbx_vector_ptr_destroy(&queries); out: runid++; }
/****************************************************************************** * * * Function: zbx_mock_test_entry * * * ******************************************************************************/ void zbx_mock_test_entry(void **state) { const char *filter; zbx_prometheus_condition_test_t *metric = NULL, *value = NULL; zbx_vector_ptr_t labels; int ret, expected_ret, index; char *error = NULL; zbx_mock_handle_t hmetric, hvalue, hlabels, hlabel; zbx_mock_error_t mock_ret; ZBX_UNUSED(state); zbx_vector_ptr_create(&labels); filter = zbx_mock_get_parameter_string("in.filter"); ret = zbx_prometheus_filter_parse(filter, &metric, &labels, &value, &error); expected_ret = zbx_mock_str_to_return_code(zbx_mock_get_parameter_string("out.return")); zbx_mock_assert_result_eq("prometheus filter parsing", expected_ret, ret); if (SUCCEED == ret) { if (ZBX_MOCK_SUCCESS != zbx_mock_parameter("out.metric", &hmetric)) hmetric = -1; test_match("metric", hmetric, metric); if (ZBX_MOCK_SUCCESS != zbx_mock_parameter("out.value", &hvalue)) hvalue = -1; test_match("value", hvalue, value); if (ZBX_MOCK_SUCCESS != zbx_mock_parameter("out.labels", &hlabels)) hlabels = -1; if (-1 != hlabels && 0 == labels.values_num) fail_msg("expected to parse label filters"); if (-1 == hlabels && 0 != labels.values_num) fail_msg("did not expect to parse label filters"); if (-1 != hlabels) { index = 0; while (ZBX_MOCK_END_OF_VECTOR != (mock_ret = zbx_mock_vector_element(hlabels, &hlabel)) && index < labels.values_num) { test_match("label", hlabel, labels.values[index]); index++; } if (ZBX_MOCK_END_OF_VECTOR != mock_ret) fail_msg("expected more than %d filter labels", index); if (index != labels.values_num) fail_msg("got more than the expected %d filter labels", index); } } if (NULL != metric) zbx_prometheus_condition_test_free(metric); if (NULL != value) zbx_prometheus_condition_test_free(value); zbx_vector_ptr_clear_ext(&labels, (zbx_clean_func_t)zbx_prometheus_condition_test_free); zbx_vector_ptr_destroy(&labels); zbx_free(error); }
/****************************************************************************** * * * Function: zbx_proc_free_processes * * * * Purpose: frees process vector read by zbx_proc_get_processes function * * * * Parameters: processes - [IN/OUT] the process vector to free * * * ******************************************************************************/ void zbx_proc_free_processes(zbx_vector_ptr_t *processes) { zbx_vector_ptr_clear_ext(processes, (zbx_mem_free_func_t)zbx_sysinfo_proc_free); }
/****************************************************************************** * * * Function: db_update_event_suppress_data * * * * Purpose: create/update event suppress data to reflect latest maintenance * * changes in cache * * * * Parameters: suppressed_num - [OUT] the number of suppressed events * * * ******************************************************************************/ static void db_update_event_suppress_data(int *suppressed_num) { zbx_vector_ptr_t event_queries, event_data; *suppressed_num = 0; zbx_vector_ptr_create(&event_queries); zbx_vector_ptr_create(&event_data); db_get_query_events(&event_queries, &event_data); if (0 != event_queries.values_num) { zbx_db_insert_t db_insert; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; int i, j, k; zbx_event_suppress_query_t *query; zbx_event_suppress_data_t *data; zbx_vector_uint64_pair_t del_event_maintenances; zbx_vector_uint64_t maintenanceids; zbx_uint64_pair_t pair; zbx_vector_uint64_create(&maintenanceids); zbx_vector_uint64_pair_create(&del_event_maintenances); db_get_query_functions(&event_queries); db_get_query_tags(&event_queries); zbx_dc_get_running_maintenanceids(&maintenanceids); DBbegin(); if (0 != maintenanceids.values_num && SUCCEED == zbx_db_lock_maintenanceids(&maintenanceids)) zbx_dc_get_event_maintenances(&event_queries, &maintenanceids); zbx_db_insert_prepare(&db_insert, "event_suppress", "event_suppressid", "eventid", "maintenanceid", "suppress_until", NULL); DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); for (i = 0; i < event_queries.values_num; i++) { query = (zbx_event_suppress_query_t *)event_queries.values[i]; zbx_vector_uint64_pair_sort(&query->maintenances, ZBX_DEFAULT_UINT64_COMPARE_FUNC); k = 0; if (FAIL != (j = zbx_vector_ptr_bsearch(&event_data, &query->eventid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) { data = (zbx_event_suppress_data_t *)event_data.values[j]; zbx_vector_uint64_pair_sort(&data->maintenances, ZBX_DEFAULT_UINT64_COMPARE_FUNC); j = 0; while (j < data->maintenances.values_num && k < query->maintenances.values_num) { if (data->maintenances.values[j].first < query->maintenances.values[k].first) { pair.first = query->eventid; pair.second = data->maintenances.values[j].first; zbx_vector_uint64_pair_append(&del_event_maintenances, pair); j++; continue; } if (data->maintenances.values[j].first > query->maintenances.values[k].first) { if (0 == query->r_eventid) { zbx_db_insert_add_values(&db_insert, __UINT64_C(0), query->eventid, query->maintenances.values[k].first, (int)query->maintenances.values[k].second); (*suppressed_num)++; } k++; continue; } if (data->maintenances.values[j].second != query->maintenances.values[k].second) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update event_suppress" " set suppress_until=%d" " where eventid=" ZBX_FS_UI64 " and maintenanceid=" ZBX_FS_UI64 ";\n", (int)query->maintenances.values[k].second, query->eventid, query->maintenances.values[k].first); if (FAIL == DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)) goto cleanup; } j++; k++; } for (;j < data->maintenances.values_num; j++) { pair.first = query->eventid; pair.second = data->maintenances.values[j].first; zbx_vector_uint64_pair_append(&del_event_maintenances, pair); } } if (0 == query->r_eventid) { for (;k < query->maintenances.values_num; k++) { zbx_db_insert_add_values(&db_insert, __UINT64_C(0), query->eventid, query->maintenances.values[k].first, (int)query->maintenances.values[k].second); (*suppressed_num)++; } } } for (i = 0; i < del_event_maintenances.values_num; i++) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from event_suppress" " where eventid=" ZBX_FS_UI64 " and maintenanceid=" ZBX_FS_UI64 ";\n", del_event_maintenances.values[i].first, del_event_maintenances.values[i].second); if (FAIL == DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)) goto cleanup; } DBend_multiple_update(&sql, &sql_alloc, &sql_offset); if (16 < sql_offset) { if (ZBX_DB_OK > DBexecute("%s", sql)) goto cleanup; } zbx_db_insert_autoincrement(&db_insert, "event_suppressid"); zbx_db_insert_execute(&db_insert); cleanup: DBcommit(); zbx_db_insert_clean(&db_insert); zbx_free(sql); zbx_vector_uint64_pair_destroy(&del_event_maintenances); zbx_vector_uint64_destroy(&maintenanceids); } zbx_vector_ptr_clear_ext(&event_data, (zbx_clean_func_t)event_suppress_data_free); zbx_vector_ptr_destroy(&event_data); zbx_vector_ptr_clear_ext(&event_queries, (zbx_clean_func_t)zbx_event_suppress_query_free); zbx_vector_ptr_destroy(&event_queries); }
/****************************************************************************** * * * Function: lld_conditions_free * * * * Purpose: release resources allocated by filter conditions * * * * Parameters: conditions - [IN] the filter conditions * * * ******************************************************************************/ static void lld_conditions_free(zbx_vector_ptr_t *conditions) { zbx_vector_ptr_clear_ext(conditions, (zbx_clean_func_t)lld_condition_free); zbx_vector_ptr_destroy(conditions); }
/****************************************************************************** * * * Function: lld_process_discovery_rule * * * * Purpose: add or update items, triggers and graphs for discovery item * * * * Parameters: lld_ruleid - [IN] discovery item identificator from database * * value - [IN] received value from agent * * * ******************************************************************************/ void lld_process_discovery_rule(zbx_uint64_t lld_ruleid, char *value, const zbx_timespec_t *ts) { const char *__function_name = "lld_process_discovery_rule"; DB_RESULT result; DB_ROW row; zbx_uint64_t hostid = 0; char *discovery_key = NULL, *error = NULL, *db_error = NULL, *error_esc; unsigned char state = 0; unsigned short lifetime; zbx_vector_ptr_t lld_rows; char *sql = NULL; size_t sql_alloc = 128, sql_offset = 0; const char *sql_start = "update items set ", *sql_continue = ","; lld_filter_t filter; time_t now; zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid:" ZBX_FS_UI64, __function_name, lld_ruleid); zbx_vector_ptr_create(&lld_rows); lld_filter_init(&filter); sql = zbx_malloc(sql, sql_alloc); result = DBselect( "select hostid,key_,state,evaltype,formula,error,lifetime" " from items" " where itemid=" ZBX_FS_UI64, lld_ruleid); if (NULL != (row = DBfetch(result))) { char *lifetime_str; ZBX_STR2UINT64(hostid, row[0]); discovery_key = zbx_strdup(discovery_key, row[1]); state = (unsigned char)atoi(row[2]); filter.evaltype = atoi(row[3]); filter.expression = zbx_strdup(NULL, row[4]); db_error = zbx_strdup(db_error, row[5]); lifetime_str = zbx_strdup(NULL, row[6]); substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL, &lifetime_str, MACRO_TYPE_COMMON, NULL, 0); if (SUCCEED != is_ushort(lifetime_str, &lifetime)) { zabbix_log(LOG_LEVEL_WARNING, "cannot process lost resources for the discovery rule \"%s:%s\":" " \"%s\" is not a valid value", zbx_host_string(hostid), discovery_key, lifetime_str); lifetime = 3650; /* max value for the field */ } zbx_free(lifetime_str); } else zabbix_log(LOG_LEVEL_WARNING, "invalid discovery rule ID [" ZBX_FS_UI64 "]", lld_ruleid); DBfree_result(result); if (0 == hostid) goto clean; if (SUCCEED != lld_filter_load(&filter, lld_ruleid, &error)) goto error; if (SUCCEED != lld_rows_get(value, &filter, &lld_rows, &error)) goto error; error = zbx_strdup(error, ""); now = time(NULL); lld_update_items(hostid, lld_ruleid, &lld_rows, &error, lifetime, now); lld_update_triggers(hostid, lld_ruleid, &lld_rows, &error); lld_update_graphs(hostid, lld_ruleid, &lld_rows, &error); lld_update_hosts(lld_ruleid, &lld_rows, &error, lifetime, now); if (ITEM_STATE_NOTSUPPORTED == state) { zabbix_log(LOG_LEVEL_WARNING, "discovery rule [" ZBX_FS_UI64 "][%s] became supported", lld_ruleid, zbx_host_key_string(lld_ruleid)); add_event(EVENT_SOURCE_INTERNAL, EVENT_OBJECT_LLDRULE, lld_ruleid, ts, ITEM_STATE_NORMAL, NULL, NULL, NULL, 0, 0, NULL, 0, NULL); process_events(); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sstate=%d", sql_start, ITEM_STATE_NORMAL); sql_start = sql_continue; } error: if (NULL != error && 0 != strcmp(error, db_error)) { error_esc = DBdyn_escape_string_len(error, ITEM_ERROR_LEN); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%serror='%s'", sql_start, error_esc); sql_start = sql_continue; zbx_free(error_esc); } if (sql_start == sql_continue) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where itemid=" ZBX_FS_UI64, lld_ruleid); DBbegin(); DBexecute("%s", sql); DBcommit(); } clean: zbx_free(error); zbx_free(db_error); zbx_free(discovery_key); zbx_free(sql); lld_filter_clean(&filter); zbx_vector_ptr_clear_ext(&lld_rows, (zbx_clean_func_t)lld_row_free); zbx_vector_ptr_destroy(&lld_rows); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
static void lld_row_free(zbx_lld_row_t *lld_row) { zbx_vector_ptr_clear_ext(&lld_row->item_links, (zbx_clean_func_t)lld_item_link_free); zbx_vector_ptr_destroy(&lld_row->item_links); zbx_free(lld_row); }