master
c 178 lines 6.32 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "dyncfg-internals.h"
4 #include "dyncfg.h"
5
6 // ----------------------------------------------------------------------------
7 // echo is when we send requests to plugins without any caller
8 // it is used for:
9 // 1. the first enable/disable requests we send, and also
10 // 2. updates to stock or user configurations
11 // 3. saved dynamic jobs we need to add to templates
12
13 struct dyncfg_echo {
14 const DICTIONARY_ITEM *item;
15 DYNCFG *df; // for additions this is the job, not the template
16 BUFFER *wb;
17 DYNCFG_CMDS cmd;
18 const char *cmd_str;
19 };
20
21 void dyncfg_echo_cb(BUFFER *wb __maybe_unused, int code __maybe_unused, void *result_cb_data) {
22 struct dyncfg_echo *e = result_cb_data;
23 DYNCFG *df = e->df;
24
25 if(DYNCFG_RESP_SUCCESS(code)) {
26 // successful response
27
28 if(e->cmd == DYNCFG_CMD_ADD) {
29 df->dyncfg.status = dyncfg_status_from_successful_response(code);
30 dyncfg_update_status_on_successful_add_or_update(df, code);
31 }
32 else if(e->cmd == DYNCFG_CMD_UPDATE) {
33 df->dyncfg.status = dyncfg_status_from_successful_response(code);
34 dyncfg_update_status_on_successful_add_or_update(df, code);
35 }
36 else if(e->cmd == DYNCFG_CMD_DISABLE)
37 df->dyncfg.status = df->current.status = DYNCFG_STATUS_DISABLED;
38 else if(e->cmd == DYNCFG_CMD_ENABLE)
39 df->dyncfg.status = df->current.status = dyncfg_status_from_successful_response(code);
40 }
41 else {
42 // failed response
43
44 nd_log(NDLS_DAEMON, NDLP_ERR,
45 "DYNCFG: received response code %d on request to id '%s', cmd: %s",
46 code, dictionary_acquired_item_name(e->item), e->cmd_str);
47
48 if(e->cmd == DYNCFG_CMD_UPDATE || e->cmd == DYNCFG_CMD_ADD)
49 e->df->dyncfg.plugin_rejected = true;
50 }
51
52 buffer_free(e->wb);
53 dictionary_acquired_item_release(dyncfg_globals.nodes, e->item);
54
55 e->wb = NULL;
56 e->df = NULL;
57 e->item = NULL;
58 freez((void *)e->cmd_str);
59 e->cmd_str = NULL;
60 freez(e);
61 }
62
63 // ----------------------------------------------------------------------------
64
65 void dyncfg_echo(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id __maybe_unused, DYNCFG_CMDS cmd) {
66 RRDHOST *host = dyncfg_rrdhost(df);
67 if(!host) {
68 nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: cannot find host of configuration id '%s'", id);
69 return;
70 }
71
72 if(!(df->cmds & cmd)) {
73 nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: attempted to echo a cmd that is not supported");
74 return;
75 }
76
77 const char *cmd_str = dyncfg_id2cmd_one(cmd);
78 if(!cmd_str) {
79 nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: command given does not resolve to a known command");
80 return;
81 }
82
83 struct dyncfg_echo *e = callocz(1, sizeof(struct dyncfg_echo));
84 e->item = dictionary_acquired_item_dup(dyncfg_globals.nodes, item);
85 e->wb = buffer_create(0, NULL);
86 e->df = df;
87 e->cmd = cmd;
88 e->cmd_str = strdupz(cmd_str);
89
90 size_t buf_size = string_strlen(df->function) + strlen(e->cmd_str) + 20;
91 CLEAN_CHAR_P *buf = mallocz(buf_size);
92 snprintfz(buf, buf_size, "%s %s", string2str(df->function), e->cmd_str);
93
94 rrd_function_run(
95 host, e->wb, 10,
96 HTTP_ACCESS_ALL, buf, false, NULL,
97 dyncfg_echo_cb, e,
98 NULL, NULL,
99 NULL, NULL,
100 NULL, string2str(df->dyncfg.source), false);
101 }
102
103 // ----------------------------------------------------------------------------
104
105 void dyncfg_echo_update(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id) {
106 RRDHOST *host = dyncfg_rrdhost(df);
107 if(!host) {
108 nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: cannot find host of configuration id '%s'", id);
109 return;
110 }
111
112 if(!df->dyncfg.payload) {
113 nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: requested to send an update to '%s', but there is no payload", id);
114 return;
115 }
116
117 struct dyncfg_echo *e = callocz(1, sizeof(struct dyncfg_echo));
118 e->item = dictionary_acquired_item_dup(dyncfg_globals.nodes, item);
119 e->wb = buffer_create(0, NULL);
120 e->df = df;
121 e->cmd = DYNCFG_CMD_UPDATE;
122 e->cmd_str = strdupz("update");
123
124 size_t buf_size = string_strlen(df->function) + strlen(e->cmd_str) + 20;
125 CLEAN_CHAR_P *buf = mallocz(buf_size);
126 snprintfz(buf, buf_size, "%s %s", string2str(df->function), e->cmd_str);
127
128 rrd_function_run(
129 host, e->wb, 10,
130 HTTP_ACCESS_ALL, buf, false, NULL,
131 dyncfg_echo_cb, e,
132 NULL, NULL,
133 NULL, NULL,
134 df->dyncfg.payload, string2str(df->dyncfg.source), false);
135 }
136
137 // ----------------------------------------------------------------------------
138
139 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) {
140 RRDHOST *host = dyncfg_rrdhost(df_template);
141 if(!host) {
142 nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: cannot find host of configuration id '%s'", id_template);
143 return;
144 }
145
146 if(!df_job->dyncfg.payload) {
147 nd_log(NDLS_DAEMON, NDLP_ERR,
148 "DYNCFG: requested to send a '%s' to '%s', but there is no payload",
149 cmd, id_template);
150 return;
151 }
152
153 struct dyncfg_echo *e = callocz(1, sizeof(struct dyncfg_echo));
154 e->item = dictionary_acquired_item_dup(dyncfg_globals.nodes, item_job);
155 e->wb = buffer_create(0, NULL);
156 e->df = df_job;
157 e->cmd = DYNCFG_CMD_ADD;
158 e->cmd_str = strdupz(cmd);
159
160 size_t buf_size = string_strlen(df_template->function) + strlen(cmd) + 20;
161 CLEAN_CHAR_P *buf = mallocz(buf_size);
162 snprintfz(buf, buf_size, "%s %s", string2str(df_template->function), cmd);
163
164 rrd_function_run(
165 host, e->wb, 10,
166 HTTP_ACCESS_ALL, buf, false, NULL,
167 dyncfg_echo_cb, e,
168 NULL, NULL,
169 NULL, NULL,
170 df_job->dyncfg.payload, string2str(df_job->dyncfg.source), false);
171 }
172
173 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) {
174 size_t buf_size = strlen(job_name) + 20;
175 CLEAN_CHAR_P *buf = mallocz(buf_size);
176 snprintfz(buf, buf_size, "add %s", job_name);
177 dyncfg_echo_payload_add(item_template, item_job, df_template, df_job, template_id, buf);
178 }