From a8220ab2d293bb7f4b014b79d16b2fb05090fa93 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Feb 2021 12:45:55 +0100 Subject: Adding upstream version 1.29.0. Signed-off-by: Daniel Baumann --- web/api/web_api_v1.c | 263 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 228 insertions(+), 35 deletions(-) (limited to 'web/api/web_api_v1.c') diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c index 3efac5669..73ac15d30 100644 --- a/web/api/web_api_v1.c +++ b/web/api/web_api_v1.c @@ -2,6 +2,8 @@ #include "web_api_v1.h" +char *api_secret; + static struct { const char *name; uint32_t hash; @@ -33,6 +35,7 @@ static struct { , {"match_names" , 0 , RRDR_OPTION_MATCH_NAMES} , {"match-names" , 0 , RRDR_OPTION_MATCH_NAMES} , {"showcustomvars" , 0 , RRDR_OPTION_CUSTOM_VARS} + , {"allow_past" , 0 , RRDR_OPTION_ALLOW_PAST} , { NULL, 0, 0} }; @@ -194,10 +197,8 @@ inline uint32_t web_client_api_request_v1_data_google_format(char *name) { return DATASOURCE_JSON; } - -inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) { +int web_client_api_request_v1_alarms_select (char *url) { int all = 0; - while(url) { char *value = mystrsep(&url, "&"); if (!value || !*value) continue; @@ -206,6 +207,12 @@ inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, else if(!strcmp(value, "active")) all = 0; } + return all; +} + +inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) { + int all = web_client_api_request_v1_alarms_select(url); + buffer_flush(w->response.data); w->response.data->contenttype = CT_APPLICATION_JSON; health_alarms2json(host, w->response.data, all); @@ -213,6 +220,16 @@ inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, return HTTP_RESP_OK; } +inline int web_client_api_request_v1_alarms_values(RRDHOST *host, struct web_client *w, char *url) { + int all = web_client_api_request_v1_alarms_select(url); + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + health_alarms_values2json(host, w->response.data, all); + buffer_no_cacheable(w->response.data); + return HTTP_RESP_OK; +} + inline int web_client_api_request_v1_alarm_count(RRDHOST *host, struct web_client *w, char *url) { RRDCALC_STATUS status = RRDCALC_STATUS_RAISED; BUFFER *contexts = NULL; @@ -333,7 +350,19 @@ inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, buffer_flush(w->response.data); w->response.data->contenttype = CT_APPLICATION_JSON; - charts2json(host, w->response.data); + charts2json(host, w->response.data, 0, 0); + return HTTP_RESP_OK; +} + +inline int web_client_api_request_v1_archivedcharts(RRDHOST *host __maybe_unused, struct web_client *w, char *url) { + (void)url; + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; +#ifdef ENABLE_DBENGINE + if (host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) + sql_rrdset2json(host, w->response.data); +#endif return HTTP_RESP_OK; } @@ -372,7 +401,9 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c , *before_str = NULL , *after_str = NULL , *group_time_str = NULL - , *points_str = NULL; + , *points_str = NULL + , *context = NULL + , *chart_label_key = NULL; int group = RRDR_GROUPING_AVERAGE; uint32_t format = DATASOURCE_JSON; @@ -391,7 +422,9 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c // name and value are now the parameters // they are not null and not empty - if(!strcmp(name, "chart")) chart = value; + if(!strcmp(name, "context")) context = value; + else if(!strcmp(name, "chart_label_key")) chart_label_key = value; + else if(!strcmp(name, "chart")) chart = value; else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { if(!dimensions) dimensions = buffer_create(100); buffer_strcat(dimensions, "|"); @@ -457,23 +490,59 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c fix_google_param(responseHandler); fix_google_param(outFileName); - if(!chart || !*chart) { + RRDSET *st = NULL; + + if((!chart || !*chart) && (!context)) { buffer_sprintf(w->response.data, "No chart id is given at the request."); goto cleanup; } - RRDSET *st = rrdset_find(host, chart); - if(!st) st = rrdset_find_byname(host, chart); - if(!st) { - buffer_strcat(w->response.data, "Chart is not found: "); - buffer_strcat_htmlescape(w->response.data, chart); + struct context_param *context_param_list = NULL; + if (context && !chart) { + RRDSET *st1; + uint32_t context_hash = simple_hash(context); + + rrdhost_rdlock(host); + rrdset_foreach_read(st1, host) { + if (st1->hash_context == context_hash && !strcmp(st1->context, context) && + (!chart_label_key || rrdset_contains_label_keylist(st1, chart_label_key))) + build_context_param_list(&context_param_list, st1); + } + rrdhost_unlock(host); + if (likely(context_param_list && context_param_list->rd)) // Just set the first one + st = context_param_list->rd->rrdset; + } + else { + st = rrdset_find(host, chart); + if (!st) + st = rrdset_find_byname(host, chart); + if (likely(st)) + st->last_accessed_time = now_realtime_sec(); + } + + if (!st && !context_param_list) { + if (context && !chart) { + if (!chart_label_key) { + buffer_strcat(w->response.data, "Context is not found: "); + buffer_strcat_htmlescape(w->response.data, context); + } else { + buffer_strcat(w->response.data, "Context: "); + buffer_strcat_htmlescape(w->response.data, context); + buffer_strcat(w->response.data, " or chart label key: "); + buffer_strcat_htmlescape(w->response.data, chart_label_key); + buffer_strcat(w->response.data, " not found"); + } + } + else { + buffer_strcat(w->response.data, "Chart is not found: "); + buffer_strcat_htmlescape(w->response.data, chart); + } ret = HTTP_RESP_NOT_FOUND; goto cleanup; } - st->last_accessed_time = now_realtime_sec(); long long before = (before_str && *before_str)?str2l(before_str):0; - long long after = (after_str && *after_str) ?str2l(after_str):0; + long long after = (after_str && *after_str) ?str2l(after_str):-600; int points = (points_str && *points_str)?str2i(points_str):0; long group_time = (group_time_str && *group_time_str)?str2l(group_time_str):0; @@ -515,7 +584,9 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c } ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, group_time - , options, &last_timestamp_in_data); + , options, &last_timestamp_in_data, context_param_list, chart_label_key); + + free_context_param_list(&context_param_list); if(format == DATASOURCE_DATATABLE_JSONP) { if(google_timestamp < last_timestamp_in_data) @@ -596,6 +667,9 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client * int redirects = 0; */ + // Don't cache registry responses + buffer_no_cacheable(w->response.data); + while(url) { char *value = mystrsep(&url, "&"); if (!value || !*value) continue; @@ -749,44 +823,119 @@ static inline void web_client_api_request_v1_info_summary_alarm_statuses(RRDHOST } static inline void web_client_api_request_v1_info_mirrored_hosts(BUFFER *wb) { - RRDHOST *rc; + RRDHOST *host; int count = 0; + + buffer_strcat(wb, "\t\"mirrored_hosts\": [\n"); rrd_rdlock(); - rrdhost_foreach_read(rc) { - if(count > 0) buffer_strcat(wb, ",\n"); - buffer_sprintf(wb, "\t\t\"%s\"", rc->hostname); + rrdhost_foreach_read(host) { + if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED)) + continue; + if (count > 0) + buffer_strcat(wb, ",\n"); + + buffer_sprintf(wb, "\t\t\"%s\"", host->hostname); + count++; + } + + buffer_strcat(wb, "\n\t],\n\t\"mirrored_hosts_status\": [\n"); + count = 0; + rrdhost_foreach_read(host) + { + if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED)) + continue; + if (count > 0) + buffer_strcat(wb, ",\n"); + + netdata_mutex_lock(&host->receiver_lock); + buffer_sprintf( + wb, "\t\t{ \"guid\": \"%s\", \"reachable\": %s, \"claim_id\": ", host->machine_guid, + (host->receiver || host == localhost) ? "true" : "false"); + netdata_mutex_unlock(&host->receiver_lock); + + rrdhost_aclk_state_lock(host); + if (host->aclk_state.claimed_id) + buffer_sprintf(wb, "\"%s\" }", host->aclk_state.claimed_id); + else + buffer_strcat(wb, "null }"); + rrdhost_aclk_state_unlock(host); + count++; } - buffer_strcat(wb, "\n"); rrd_unlock(); + + buffer_strcat(wb, "\n\t],\n"); } -inline int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, char *url) { - (void)url; - if (!netdata_ready) return HTTP_RESP_BACKEND_FETCH_FAILED; +inline void host_labels2json(RRDHOST *host, BUFFER *wb, size_t indentation) { + char tabs[11]; - BUFFER *wb = w->response.data; - buffer_flush(wb); - wb->contenttype = CT_APPLICATION_JSON; + if (indentation > 10) + indentation = 10; + + tabs[0] = '\0'; + while (indentation) { + strcat(tabs, "\t"); + indentation--; + } + + int count = 0; + rrdhost_rdlock(host); + netdata_rwlock_rdlock(&host->labels.labels_rwlock); + for (struct label *label = host->labels.head; label; label = label->next) { + if(count > 0) buffer_strcat(wb, ",\n"); + buffer_strcat(wb, tabs); + + char value[CONFIG_MAX_VALUE * 2 + 1]; + sanitize_json_string(value, label->value, CONFIG_MAX_VALUE * 2); + buffer_sprintf(wb, "\"%s\": \"%s\"", label->key, value); + count++; + } + buffer_strcat(wb, "\n"); + netdata_rwlock_unlock(&host->labels.labels_rwlock); + rrdhost_unlock(host); +} + +extern int aclk_connected; +inline int web_client_api_request_v1_info_fill_buffer(RRDHOST *host, BUFFER *wb) +{ buffer_strcat(wb, "{\n"); buffer_sprintf(wb, "\t\"version\": \"%s\",\n", host->program_version); buffer_sprintf(wb, "\t\"uid\": \"%s\",\n", host->machine_guid); - buffer_strcat(wb, "\t\"mirrored_hosts\": [\n"); web_client_api_request_v1_info_mirrored_hosts(wb); - buffer_strcat(wb, "\t],\n"); buffer_strcat(wb, "\t\"alarms\": {\n"); web_client_api_request_v1_info_summary_alarm_statuses(host, wb); buffer_strcat(wb, "\t},\n"); - buffer_sprintf(wb, "\t\"os_name\": %s,\n", (host->system_info->os_name) ? host->system_info->os_name : "\"\""); - buffer_sprintf(wb, "\t\"os_id\": \"%s\",\n", (host->system_info->os_id) ? host->system_info->os_id : ""); - buffer_sprintf(wb, "\t\"os_id_like\": \"%s\",\n", (host->system_info->os_id_like) ? host->system_info->os_id_like : ""); - buffer_sprintf(wb, "\t\"os_version\": \"%s\",\n", (host->system_info->os_version) ? host->system_info->os_version : ""); - buffer_sprintf(wb, "\t\"os_version_id\": \"%s\",\n", (host->system_info->os_version_id) ? host->system_info->os_version_id : ""); - buffer_sprintf(wb, "\t\"os_detection\": \"%s\",\n", (host->system_info->os_detection) ? host->system_info->os_detection : ""); + buffer_sprintf(wb, "\t\"os_name\": \"%s\",\n", (host->system_info->host_os_name) ? host->system_info->host_os_name : ""); + buffer_sprintf(wb, "\t\"os_id\": \"%s\",\n", (host->system_info->host_os_id) ? host->system_info->host_os_id : ""); + buffer_sprintf(wb, "\t\"os_id_like\": \"%s\",\n", (host->system_info->host_os_id_like) ? host->system_info->host_os_id_like : ""); + buffer_sprintf(wb, "\t\"os_version\": \"%s\",\n", (host->system_info->host_os_version) ? host->system_info->host_os_version : ""); + buffer_sprintf(wb, "\t\"os_version_id\": \"%s\",\n", (host->system_info->host_os_version_id) ? host->system_info->host_os_version_id : ""); + buffer_sprintf(wb, "\t\"os_detection\": \"%s\",\n", (host->system_info->host_os_detection) ? host->system_info->host_os_detection : ""); + buffer_sprintf(wb, "\t\"cores_total\": \"%s\",\n", (host->system_info->host_cores) ? host->system_info->host_cores : ""); + buffer_sprintf(wb, "\t\"total_disk_space\": \"%s\",\n", (host->system_info->host_disk_space) ? host->system_info->host_disk_space : ""); + buffer_sprintf(wb, "\t\"cpu_freq\": \"%s\",\n", (host->system_info->host_cpu_freq) ? host->system_info->host_cpu_freq : ""); + buffer_sprintf(wb, "\t\"ram_total\": \"%s\",\n", (host->system_info->host_ram_total) ? host->system_info->host_ram_total : ""); + + if (host->system_info->container_os_name) + buffer_sprintf(wb, "\t\"container_os_name\": \"%s\",\n", host->system_info->container_os_name); + if (host->system_info->container_os_id) + buffer_sprintf(wb, "\t\"container_os_id\": \"%s\",\n", host->system_info->container_os_id); + if (host->system_info->container_os_id_like) + buffer_sprintf(wb, "\t\"container_os_id_like\": \"%s\",\n", host->system_info->container_os_id_like); + if (host->system_info->container_os_version) + buffer_sprintf(wb, "\t\"container_os_version\": \"%s\",\n", host->system_info->container_os_version); + if (host->system_info->container_os_version_id) + buffer_sprintf(wb, "\t\"container_os_version_id\": \"%s\",\n", host->system_info->container_os_version_id); + if (host->system_info->container_os_detection) + buffer_sprintf(wb, "\t\"container_os_detection\": \"%s\",\n", host->system_info->container_os_detection); + if (host->system_info->is_k8s_node) + buffer_sprintf(wb, "\t\"is_k8s_node\": \"%s\",\n", host->system_info->is_k8s_node); + buffer_sprintf(wb, "\t\"kernel_name\": \"%s\",\n", (host->system_info->kernel_name) ? host->system_info->kernel_name : ""); buffer_sprintf(wb, "\t\"kernel_version\": \"%s\",\n", (host->system_info->kernel_version) ? host->system_info->kernel_version : ""); buffer_sprintf(wb, "\t\"architecture\": \"%s\",\n", (host->system_info->architecture) ? host->system_info->architecture : ""); @@ -795,11 +944,53 @@ inline int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, c buffer_sprintf(wb, "\t\"container\": \"%s\",\n", (host->system_info->container) ? host->system_info->container : ""); buffer_sprintf(wb, "\t\"container_detection\": \"%s\",\n", (host->system_info->container_detection) ? host->system_info->container_detection : ""); + buffer_strcat(wb, "\t\"host_labels\": {\n"); + host_labels2json(host, wb, 2); + buffer_strcat(wb, "\t},\n"); + buffer_strcat(wb, "\t\"collectors\": ["); chartcollectors2json(host, wb); - buffer_strcat(wb, "\n\t]\n"); + buffer_strcat(wb, "\n\t],\n"); + +#ifdef DISABLE_CLOUD + buffer_strcat(wb, "\t\"cloud-enabled\": false,\n"); +#else + buffer_sprintf(wb, "\t\"cloud-enabled\": %s,\n", + appconfig_get_boolean(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", 1) ? "true" : "false"); +#endif + +#ifdef ENABLE_ACLK + buffer_strcat(wb, "\t\"cloud-available\": true,\n"); +#else + buffer_strcat(wb, "\t\"cloud-available\": false,\n"); +#endif + char *agent_id = is_agent_claimed(); + if (agent_id == NULL) + buffer_strcat(wb, "\t\"agent-claimed\": false,\n"); + else { + buffer_strcat(wb, "\t\"agent-claimed\": true,\n"); + freez(agent_id); + } +#ifdef ENABLE_ACLK + if (aclk_connected) + buffer_strcat(wb, "\t\"aclk-available\": true\n"); + else +#endif + buffer_strcat(wb, "\t\"aclk-available\": false\n"); // Intentionally valid with/without #ifdef above buffer_strcat(wb, "}"); + return 0; +} + +inline int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, char *url) { + (void)url; + if (!netdata_ready) return HTTP_RESP_BACKEND_FETCH_FAILED; + BUFFER *wb = w->response.data; + buffer_flush(wb); + wb->contenttype = CT_APPLICATION_JSON; + + web_client_api_request_v1_info_fill_buffer(host, wb); + buffer_no_cacheable(wb); return HTTP_RESP_OK; } @@ -814,6 +1005,7 @@ static struct api_command { { "data", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_data }, { "chart", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_chart }, { "charts", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_charts }, + { "archivedcharts", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_archivedcharts }, // registry checks the ACL by itself, so we allow everything { "registry", 0, WEB_CLIENT_ACL_NOCHECK, web_client_api_request_v1_registry }, @@ -822,6 +1014,7 @@ static struct api_command { { "badge.svg", 0, WEB_CLIENT_ACL_DASHBOARD|WEB_CLIENT_ACL_BADGE, web_client_api_request_v1_badge }, { "alarms", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarms }, + { "alarms_values", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarms_values }, { "alarm_log", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_log }, { "alarm_variables", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_variables }, { "alarm_count", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_count }, -- cgit v1.2.3