summaryrefslogtreecommitdiffstats
path: root/src/daemon/config/dyncfg-echo.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/daemon/config/dyncfg-echo.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/daemon/config/dyncfg-echo.c b/src/daemon/config/dyncfg-echo.c
new file mode 100644
index 000000000..95d40a025
--- /dev/null
+++ b/src/daemon/config/dyncfg-echo.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "dyncfg-internals.h"
+#include "dyncfg.h"
+
+// ----------------------------------------------------------------------------
+// echo is when we send requests to plugins without any caller
+// it is used for:
+// 1. the first enable/disable requests we send, and also
+// 2. updates to stock or user configurations
+// 3. saved dynamic jobs we need to add to templates
+
+struct dyncfg_echo {
+ const DICTIONARY_ITEM *item;
+ DYNCFG *df; // for additions this is the job, not the template
+ BUFFER *wb;
+ DYNCFG_CMDS cmd;
+ const char *cmd_str;
+};
+
+void dyncfg_echo_cb(BUFFER *wb __maybe_unused, int code __maybe_unused, void *result_cb_data) {
+ struct dyncfg_echo *e = result_cb_data;
+ DYNCFG *df = e->df;
+
+ if(DYNCFG_RESP_SUCCESS(code)) {
+ // successful response
+
+ if(e->cmd == DYNCFG_CMD_ADD) {
+ df->dyncfg.status = dyncfg_status_from_successful_response(code);
+ dyncfg_update_status_on_successful_add_or_update(df, code);
+ }
+ else if(e->cmd == DYNCFG_CMD_UPDATE) {
+ df->dyncfg.status = dyncfg_status_from_successful_response(code);
+ dyncfg_update_status_on_successful_add_or_update(df, code);
+ }
+ else if(e->cmd == DYNCFG_CMD_DISABLE)
+ df->dyncfg.status = df->current.status = DYNCFG_STATUS_DISABLED;
+ else if(e->cmd == DYNCFG_CMD_ENABLE)
+ df->dyncfg.status = df->current.status = dyncfg_status_from_successful_response(code);
+ }
+ else {
+ // failed response
+
+ nd_log(NDLS_DAEMON, NDLP_ERR,
+ "DYNCFG: received response code %d on request to id '%s', cmd: %s",
+ code, dictionary_acquired_item_name(e->item), e->cmd_str);
+
+ if(e->cmd == DYNCFG_CMD_UPDATE || e->cmd == DYNCFG_CMD_ADD)
+ e->df->dyncfg.plugin_rejected = true;
+ }
+
+ buffer_free(e->wb);
+ dictionary_acquired_item_release(dyncfg_globals.nodes, e->item);
+
+ e->wb = NULL;
+ e->df = NULL;
+ e->item = NULL;
+ freez((void *)e->cmd_str);
+ e->cmd_str = NULL;
+ freez(e);
+}
+
+// ----------------------------------------------------------------------------
+
+void dyncfg_echo(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id __maybe_unused, DYNCFG_CMDS cmd) {
+ RRDHOST *host = dyncfg_rrdhost(df);
+ if(!host) {
+ nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: cannot find host of configuration id '%s'", id);
+ return;
+ }
+
+ if(!(df->cmds & cmd)) {
+ nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: attempted to echo a cmd that is not supported");
+ return;
+ }
+
+ const char *cmd_str = dyncfg_id2cmd_one(cmd);
+ if(!cmd_str) {
+ nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: command given does not resolve to a known command");
+ return;
+ }
+
+ struct dyncfg_echo *e = callocz(1, sizeof(struct dyncfg_echo));
+ e->item = dictionary_acquired_item_dup(dyncfg_globals.nodes, item);
+ e->wb = buffer_create(0, NULL);
+ e->df = df;
+ e->cmd = cmd;
+ e->cmd_str = strdupz(cmd_str);
+
+ char buf[string_strlen(df->function) + strlen(e->cmd_str) + 20];
+ snprintfz(buf, sizeof(buf), "%s %s", string2str(df->function), e->cmd_str);
+
+ rrd_function_run(
+ host, e->wb, 10,
+ HTTP_ACCESS_ALL, buf, false, NULL,
+ dyncfg_echo_cb, e,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, string2str(df->dyncfg.source));
+}
+
+// ----------------------------------------------------------------------------
+
+void dyncfg_echo_update(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id) {
+ RRDHOST *host = dyncfg_rrdhost(df);
+ if(!host) {
+ nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: cannot find host of configuration id '%s'", id);
+ return;
+ }
+
+ if(!df->dyncfg.payload) {
+ nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: requested to send an update to '%s', but there is no payload", id);
+ return;
+ }
+
+ struct dyncfg_echo *e = callocz(1, sizeof(struct dyncfg_echo));
+ e->item = dictionary_acquired_item_dup(dyncfg_globals.nodes, item);
+ e->wb = buffer_create(0, NULL);
+ e->df = df;
+ e->cmd = DYNCFG_CMD_UPDATE;
+ e->cmd_str = strdupz("update");
+
+ char buf[string_strlen(df->function) + strlen(e->cmd_str) + 20];
+ snprintfz(buf, sizeof(buf), "%s %s", string2str(df->function), e->cmd_str);
+
+ rrd_function_run(
+ host, e->wb, 10,
+ HTTP_ACCESS_ALL, buf, false, NULL,
+ dyncfg_echo_cb, e,
+ NULL, NULL,
+ NULL, NULL,
+ df->dyncfg.payload, string2str(df->dyncfg.source));
+}
+
+// ----------------------------------------------------------------------------
+
+static void dyncfg_echo_payload_add(const DICTIONARY_ITEM *item_template __maybe_unused, const DICTIONARY_ITEM *item_job, DYNCFG *df_template, DYNCFG *df_job, const char *id_template, const char *cmd) {
+ RRDHOST *host = dyncfg_rrdhost(df_template);
+ if(!host) {
+ nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: cannot find host of configuration id '%s'", id_template);
+ return;
+ }
+
+ if(!df_job->dyncfg.payload) {
+ nd_log(NDLS_DAEMON, NDLP_ERR,
+ "DYNCFG: requested to send a '%s' to '%s', but there is no payload",
+ cmd, id_template);
+ return;
+ }
+
+ struct dyncfg_echo *e = callocz(1, sizeof(struct dyncfg_echo));
+ e->item = dictionary_acquired_item_dup(dyncfg_globals.nodes, item_job);
+ e->wb = buffer_create(0, NULL);
+ e->df = df_job;
+ e->cmd = DYNCFG_CMD_ADD;
+ e->cmd_str = strdupz(cmd);
+
+ char buf[string_strlen(df_template->function) + strlen(cmd) + 20];
+ snprintfz(buf, sizeof(buf), "%s %s", string2str(df_template->function), cmd);
+
+ rrd_function_run(
+ host, e->wb, 10,
+ HTTP_ACCESS_ALL, buf, false, NULL,
+ dyncfg_echo_cb, e,
+ NULL, NULL,
+ NULL, NULL,
+ df_job->dyncfg.payload, string2str(df_job->dyncfg.source));
+}
+
+void dyncfg_echo_add(const DICTIONARY_ITEM *item_template, const DICTIONARY_ITEM *item_job, DYNCFG *df_template, DYNCFG *df_job, const char *template_id, const char *job_name) {
+ char buf[strlen(job_name) + 20];
+ snprintfz(buf, sizeof(buf), "add %s", job_name);
+ dyncfg_echo_payload_add(item_template, item_job, df_template, df_job, template_id, buf);
+}
+